C ++ - вызов функции при изменении значения члена - PullRequest
2 голосов
/ 05 февраля 2012

Моя цель - запустить приемник событий при изменении значения в классе.Мое решение этого заключается в использовании функций get и set.Тем не менее, я не хочу никаких проблем с производительностью при чтении значений.В классе ниже:

class Vertex {
 public:
  const double& GetX() { return _x; } // should inline automatically
  const double& GetY() { return _y; } // ' '                     ' '
  void SetX(const double& x); // complex stuff in source file
  void SetY(const double& y); // ' '                      ' '
 private:
  double _x, _y;
}

Я поместил определение геттеров в заголовочные файлы, потому что это должно позволить им быть встроенными.

Мой вопрос: есть ли способавтоматически вызывать функцию при изменении значения, которое не требует от меня включения определений функций в заголовочный файл?Или, возможно, существует уровень видимости, который позволяет любому читать данные, но только сам класс может их изменять?Или, может быть, что-то еще?

Я знаю, что альтернативный подход будет вручную вызывать функцию обновления, но это выглядит некрасиво:

vertex.X = 5;
vertex.Update();

Заранее благодарю.1013 * Редактировать:

До сих пор я слышал несколько замечательных ответов.Решение зависит от вашей цели:

  • Легко: добытчики и установщики;хотя и не очень чистый.
  • Clean: класс свойств (или прокси);Однако реализовать операторы не так просто.

Однако как насчет эффективности?

Я только что разработал хороший трюк для отдельных разрешений на чтение / запись, о которых я говорил ранее:

class Vertex {
 public:
  Vertex(double x, double y)
      : _x(x), _y(y), X(_x), Y(_y) { } // defined here for readability
  void SetX(double x) { _x = x; update(); } // defined here for readability
  void SetY(double y) { _y = y; update(); } // update would be the callback
  const double& X, Y;
 private:
  double _x, _y;
}

Ответы [ 2 ]

8 голосов
/ 05 февраля 2012

Если все, что вы ищете, чисто, то, вероятно, самый чистый способ сделать это - иметь объект "свойства", как в C #:

template<typename T>
class Property {
public:
    Property(std::function<void(T)> callback) : data(), callback(callback) { }

    Property& operator=(const T& newvalue) {
        data = newvalue;
        callback(data);

        return *this;
    }

    operator T() const {
        return data;
    }

private:
    T data;
    std::function<void(T)> callback;
};

class Vertex {
public:
    Vertex() : X(&xcallback), Y(&ycallback) { }

    Property<double> X, Y;
};

(Функции для краткости встроены в SO, вы можете переместить их, если хотите.) Затем вы можете сделать

Vertex v;

v.X = 4;
v.Y = 2.3443;

И каждый раз, когда значение присваивается, будет вызываться соответствующий обратный вызов. И вы можете использовать v.X и v.Y вместо того, где бы вы ни использовали double, чтобы они вели себя как обычные double с (за исключением того факта, что вам нужно было бы реализовать -=, += и т. Д.).

0 голосов
/ 05 февраля 2012

Не оптимизируйте преждевременно.Напишите код, который будет простым и легким для понимания / изменения, и только после того, как вы профилируете и увидите, что у вас действительно есть узкое место, оптимизируйте.вызовите обработчик события для метода set.

Нет модификатора доступа, который позволял бы читать данные, но ограничивал доступ только к классу.

Кроме того, вы не обязаны включать определение функции в заголовочный файл.Стоимость дополнительных инструкций по прыжкам составляет 99% времени.

...