我的目标是当类中的值发生更改时触发事件接收器。我的解决方案是使用 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;
}
我将 getter 的定义放在头文件中,因为这应该允许它们内联。
我的问题是:有没有什么方法可以在值更改时自动调用函数,而不需要我在头文件中包含函数定义?或者是否有一个可见性级别允许任何人读取数据,但只有类本身可以修改它?或者也许还有其他什么?
我知道另一种方法是手动调用更新函数,但这看起来很难看:
vertex.X = 5;
vertex.Update();
提前谢谢您。
编辑:
到目前为止,我已经听到了一些很好的答案。解决方案取决于您的目标:
但是,效率呢?
我刚刚为我之前推测的单独的读/写访问权限想出了一个很好的技巧:
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;
}
如果您要寻找的只是干净,那么最干净的方法可能是拥有一个“属性”对象,就像在 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;
};
(为了简洁起见,这些函数是内联的,如果你愿意,你可以将它们移出。)然后你就可以了
Vertex v;
v.X = 4;
v.Y = 2.3443;
并且每次赋值时,都会调用相应的回调。您也可以使用
v.X
和 v.Y
来代替任何需要使用 double
的地方,这样它们的行为就像普通的 double
(除了您必须实现 -=
之外, +=
等)。
不要过早优化。编写简单且易于理解/修改的代码,只有在分析并发现确实存在瓶颈之后,才能进行优化。
我会采用
get
/set
方法,并在 set
方法上调用事件处理程序。
没有允许您读取数据的访问修饰符,但仅限于类的访问。
此外,您不需要在头文件中包含函数定义。额外跳转指令的成本在 99% 的情况下可以忽略不计。