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&
而不是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中的类方法及属性总结举例,编写memcached启动脚本举例