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

发布于 2025-01-02 02:56:06 字数 1261 浏览 2 评论 0原文

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

提前谢谢您。

编辑:

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

  • 简单:getters 和 setters;虽然不是很干净。
  • 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;
}

My goal is to fire a event receiver when a value is changed in a class. My solution to this is using get and set functions. However, I do not want any performance problems when reading the values. In the class below:

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;
}

I put the definition of the getters in the header files, because this should allow them to be inlined.

My question is: is there any way to automatically call a function when a value is changed that does not require me to include function definitions in the header file? Or is there perhaps a visibility level that allows anyone to read the data, but only the class itself to modify it? Or maybe something else?

I know an alternative approach would be manually calling an update function, but that looks ugly:

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

Thank you in advance.

Edit:

So far I've heard some great answers. The solution depends on your goal:

  • Easy: getters and setters; not very clean though.
  • Clean: property class (or proxy); implementing operators is not as easy though.

However, what about efficiency?

I just worked out a nice trick for the separate read/write-access permissions I speculated about earlier:

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

桃酥萝莉 2025-01-09 02:56:06

如果您要寻找的只是干净,那么最干净的方法可能是拥有一个“属性”对象,就像在 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;

并且每次赋值时,都会调用相应的回调。您也可以使用 vXvY 来代替任何使用 double 的地方,这样它们的行为就像正常的 double< /code>s(除了您必须实现 -=+= 等这一事实)。

If all you're looking for is clean, then probably the cleanest way to do this would be to have a "property" object, like in 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;
};

(The functions are inline for conciseness on SO, you can move them out if you want.) Then you can do

Vertex v;

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

And every time the value is assigned to, the respective callback will be called. And you can use v.X and v.Y in place of wherever you'd use a double as well so they behave like normal doubles (except for the fact that you'd have to implement -=, +=, etc).

下壹個目標 2025-01-09 02:56:06

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

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

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

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

Don't optimize prematurely. Write code that is simple and easy to understand/modify, and only after you profile and see that indeed you have a bottleneck there, optimize.

I would go with the get/set approach, and call the event handler on the set method.

There is no access modifier that allows you to read data, but restrict access to only the class.

Also, you're not required to include the function definition in the header file. The cost of an extra jump instruction is 99% of the time negligeable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文