C++ - 更改成员值时的函数调用

RPF*_*ltz 2 c++ events encapsulation vertex getter-setter

我的目标是在类中更改值时触发事件接收器.我的解决方案是使用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;
}
Run Code Online (Sandbox Code Playgroud)

我把getter的定义放在头文件中,因为这应该允许它们被内联.

我的问题是:有什么方法可以在更改值时自动调用函数,而不需要在头文件中包含函数定义?或者是否有可见性级别允许任何人读取数据,但只有类本身才能修改它?或者别的什么?

我知道另一种方法是手动调用更新函数,但这看起来很难看:

vertex.X = 5;
vertex.Update();
Run Code Online (Sandbox Code Playgroud)

先感谢您.

编辑:

到目前为止,我听到了一些很棒的答案.解决方案取决于您的目标:

  • 容易:吸气剂和二传手; 虽然不是很干净.
  • 清洁:属性类(或代理); 实现运营商并不是那么容易.

但是,效率怎么样?

我刚刚为我之前推测的单独的读/写访问权限制定了一个很好的技巧:

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;
}
Run Code Online (Sandbox Code Playgroud)

Set*_*gie 8

如果您正在寻找的只是干净的,那么最简单的方法就是拥有一个"属性"对象,就像在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;
};
Run Code Online (Sandbox Code Playgroud)

(这些函数在SO上是内联的简洁,你可以根据需要将它们移出.)然后就可以了

Vertex v;

v.X = 4;
v.Y = 2.3443;
Run Code Online (Sandbox Code Playgroud)

每次分配值时,都会调用相应的回调.您还可以使用v.Xv.Y到位的地方,你会使用一个double,以及使他们的行为像正常的doubleS(除了事实,你必须执行-=,+=等等).