C++ 中与 Python 属性等价的实现

8 投票
3 回答
2871 浏览
提问于 2025-04-16 23:51

在C++中有没有类似Python属性的东西?还是说用获取器和设置器(getter和setter)来做会更好呢?

3 个回答

7

标准的C++没有属性这个概念。不过,如果你是在微软的平台上开发,可以使用他们提供的语言扩展:

http://msdn.microsoft.com/en-us/library/yhfk0thd.aspx

17

在C++中,你要么是在调用一个成员函数,要么是在访问一个数据成员。Python的属性其实就是用访问数据成员的方式来实现调用成员函数的效果,而在C++中没有一个合理的方法来做到这一点。

理论上,你可以用宏来搞定这个,比如说 #define looks_like_data really_a_function(),但这样做既不美观,也不合理。让一个函数看起来像数据的唯一必要原因,是为了和旧的调用代码保持兼容,那些代码曾经把它当作数据来用。但是在C++中,这样做并不能保证二进制兼容性,甚至在源代码上也不兼容,因为这个宏会破坏那些已经在其他地方用 looks_like_data 作为名字的调用代码。所以这样做其实没什么意义。

你还可以做的另一件事是创建一个实际的数据成员,作为数据的“逻辑”类型的代理:

struct Proxy {
    Foo *foo;
    Proxy(Foo *foo) : foo(foo) { }
    operator int() const {
        // getter code goes here,
        // use (const Foo*)foo rather than foo
    }
    Proxy &operator=(int a) {
       // setter code goes here
    }
    // optionally also implement boilerplate +=, -=, etc.
};

struct Foo {
    // optionally 
    // friend class Proxy;
    Proxy looks_like_data;
    Foo() : looks_like_data(this) { }
};

这几乎是合理的,但还不完全合理。使用隐式转换仍然会破坏源代码兼容性,因为有个规则是链中只能有一个用户定义的隐式转换,所以如果调用者在 looks_like_data 真的还是一个 int 的时候写了代码,并且他们的代码隐式地把那个 int 转换成了 Bar,那么一旦 looks_like_data 变成了 Proxy,它就不再隐式转换成 Bar,这样一来,你还是破坏了他们的代码。

所以经过这些分析,如果你的类真的需要一些看起来像读写属性的东西,最好还是使用getter/setter函数。

13

是的,在C++中,明确的获取器(getter)和设置器(setter)是最接近这个概念的结构。

撰写回答