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

问题描述 投票:0回答:2

我的目标是当类中的值发生更改时触发事件接收器。我的解决方案是使用 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();

提前谢谢您。

编辑:

到目前为止,我已经听到了一些很好的答案。解决方案取决于您的目标:

  • 简单:getter 和 setter;虽然不是很干净。
  • 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;
}
c++ events encapsulation getter-setter vertex
2个回答
11
投票

如果您要寻找的只是干净,那么最干净的方法可能是拥有一个“属性”对象,就像在 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
(除了您必须实现
-=
之外,
+=
等)。


0
投票

不要过早优化。编写简单且易于理解/修改的代码,只有在分析并发现确实存在瓶颈之后,才能进行优化。

我会采用

get
/
set
方法,并在
set
方法上调用事件处理程序。

没有允许您读取数据的访问修饰符,但仅限于类的访问。

此外,您不需要在头文件中包含函数定义。额外跳转指令的成本在 99% 的情况下可以忽略不计。

© www.soinside.com 2019 - 2024. All rights reserved.