C++ 中的类属性变量

Posted

技术标签:

【中文标题】C++ 中的类属性变量【英文标题】:Property-like variable in C++ 【发布时间】:2013-03-07 13:29:56 【问题描述】:

我知道类属性对象的实现已经讨论过很多次了,但是我需要的和提出的各种解决方案略有不同。

我想要的是一个与变量具有相同语义的对象,但是当它的值改变时,我想执行一些操作。这意味着拥有隐式 get/set 方法,实现运算符 = 和隐式转换运算符的重载。

请注意,当我的意思是“类属性”时,我的意思不一定是语义 object.property,而只是一种具有隐式 get/set 方法的方式(如 property-like-variable = value)。原因是我有一些使用变量的现有代码,我想在每次变量值更改时执行一些操作而不更改现有代码(只有变量的声明应该更改)。

我用这样的最少代码获得了这个结果:

#include <stdio.h>

class Int

    int _value;

public:
    // default constructor
    Int()  printf("Int: initial value undefined\n"); 

    // assignment constructor
    Int(int value) : _value(value)  printf("Int: initial value is %d\n", _value); 

    // property get
    operator const int() const  return _value; 

    // property set
    int operator=(int value)
     
        _value = value;
        printf("new value is %d\n", value);
        return value;
    

    // TODO: overload other operators if needed
;

这是一个示例用法:

class C

    Int _i;

public:
    C() : _i(2)  

    void foo()
    
        _i = 3;
        printf("foo(): _i = %d\n", _i);
    
;

int main()

    int i;
    Int I;

    i = 1;
    I = i;
    I = I + 1;

    C c;
    c.foo();

现在有一些问题:

    是否已经讨论过这一特定需求?有设计模式吗? 我在这里做坏事? (从实现和设计的角度来看) 这样做在性能方面存在一些劣势,或者编译器能够在没有开销的情况下对其进行优化? 有更好的方法来调用这个构造吗?因为这似乎不是严格意义上的“属性”(这似乎更类似于“装箱”类中的变量)。 这可以用模板概括吗?我没有看到一个简单的方法来做到这一点,因为需要做这些事情是在获取/设置值时执行自定义的事情。

【问题讨论】:

我将其简称为“包装类”,将int 包装在稍微不同的 API 中,但也许有更好的词来形容它。 我最近使用了一个类似的模式...但是,它与 C++11 的auto 结合使用是有问题的,因为在这种情况下不会调用转换运算符并复制包装器-class 可能是不受欢迎的。 【参考方案1】:

广告问题 2:我发现您的代码存在两个一般性问题:

    operator const int() 声明中的第一个 const 限定符毫无意义(gcc 对此发出警告)

    赋值运算符的返回类型应该是Int&amp; 而不是int 否则它将具有与原始int 不同的语义并且以下c++ 代码将无法编译:

    Int i;
    (i=2)=3;
    

广告问题 3:如果您的 set/get 函数除了分配/返回值什么都不做,那么它们应该被完全优化。但是,如果您致电printf(),您可能会严重陷入性能问题;)。

广告问题5:模板的泛化似乎很困难,包括通过模板sepcialization为不同类型定制它:

template<typename T> class observe

    T _value;

public:
    // default constructor
    observe()  cout << "Int: initial value undefined" << endl; 

    // assignment constructor
    observe(const T& v) : _value(v)  cout << "initial value is " << v << endl; 

    // property get
    operator T() const  return _value; 

    // property set
    observe<T>& operator=(const T& value)
    
        _value = value;
        cout << "new value is " << _value << endl;
        return *this;
    
;

// special behavior for the assignment of doubles
template<> observe<double>& observe<double>::operator =(const double& value)

    _value = value;
    cout << "new double value is " << _value << endl;
    return *this;


observe<double> d;
d = 1.0;

【讨论】:

感谢您的有用说明。关于无意义的 const 限定符,我承认这些限定符的语义对我来说总是有点模糊......为什么它没有意义?我没有现成的 GCC 设置,我的编译器 (MS VC++ 2005) 没有报告任何警告。 GCC 究竟报告了什么警告?谢谢!!! warning: type qualifiers ignored on function return type [-Wignored-qualifiers] 有趣的是,当我将额外的 const 添加到我建议的“模板化”版本时,它无法产生此警告。【参考方案2】:

我认为要使它更像一个属性,“set”代码需要在class C 中。这个怎么样:

class C

public:
    class i_property_class 

...methods from your current Int class

     i;

...rest of class C

如果可行,那么您可能想为i_property_class 尝试一个基类,并对其进行扩展,提供您必须的方法,并根据需要覆盖(注意,继承operator= 可以是tricky)以获得自定义每个单独属性的行为。

然后关于你的问题 5,让这个基类成为模板也应该可以。

【讨论】:

class C 此处仅用作示例用法。在我的真实世界场景中,我的类属性变量是围绕枚举构建的,并在整个应用程序中使用。关于模板基类,我将如何在不使用虚函数的情况下处理“set 方法”(每个实现都有自定义行为)? 我不确定您是否可以有意义地继承operator=(您的意思是通过“设置方法”,对吗?),如果您只是在派生类中覆盖它可能会更容易。在任何情况下,都不需要通过基类指针访问属性(或者至少如果您认为不允许访问属性可能会更好),因此不需要虚拟方法。

以上是关于C++ 中的类属性变量的主要内容,如果未能解决你的问题,请参考以下文章

Python中的类和方法使用举例

Python中的类方法及属性总结举例,编写memcached启动脚本举例

为啥我不能在 C++ 中更新我的类属性?

C++ 类的继承一(访问控制)

python中的类中属性元素加self.和不加self.的区别

python中的类中属性元素加self.和不加self.的区别