在C ++中是否可以通过类似属性的语法调用访问器?

时间:2016-04-22 16:22:57

标签: c++ refactoring encapsulation accessor

我正在使用大型代码库,并且有许多公开定义的变量。不幸的是,访问这些变量的功能已经改变,这个新功能最好由公共​​访问器和私有实例变量封装。

所以,我试图做出这个改变。为此,我计划将每个公共属性设为私有,然后创建访问器。但是,我不想更改任何访问旧公共属性的代码。例如:

将公共属性更改为私有后,我有以下类:

class Test {

    private:
        int item = 5;

    public:
        int GetItem() {
             return item;
        };

        void SetItem(int new_item) {
             item = new_item;
        };
};

过去,“item”曾经是该类的公共属性,可通过以下方式访问:

Test* t = new Test();
int item = t->item;

现在,我需要为检索“item”的方式添加新功能。例如:

int GetItem() {
     //  Some complicated code which changes "item"
     return item;
};

如何保持相同的语法:

int item = t->item;

但这实际上有效:

int item = t->GetItem();

非常感谢任何帮助!

4 个答案:

答案 0 :(得分:5)

您可以通过将int item = t.item;定义为成员变量来使item正常工作,该变量的类型是定义了自定义转换operator int()的帮助程序类。此外,operator=(int new_value)拦截设置操作。

你无法工作的是

int& item = t.item;

int* pitem = &t.item;

因为这两者都可以直接访问内存,而无需通过任何getter或setter。在创建引用或指针时,您甚至无法确定将有多少次访问,或者它们是读还是写。

答案 1 :(得分:1)

如果您的问题是基于您不想调用2个不同的函数进行设置和获取,则可以创建一个返回该成员引用的函数:

{
    "error": {
       "field": "amount",
       "message": "The amount isn't correct - Sufficient credit."
    }
}

如您所见,返回类型为int&而不是int。所以你可以这样使用这个功能

int& Item()
{
     // Some complicated code which changes *items
     return item;
}

答案 2 :(得分:1)

C ++是一种编译的非反射语言,即你不能只是“在访问元素时查找名称”,因为在二进制文件中,不再有名字了。

所以,不,你想要的是不可能的。 (至少不是没有限制 - 参见Ben Voigt的excellent answer;拥有一个“透明”的属性,实际上是一个吸气剂,肯定不值得你用它构建的陷阱 - )

另外,请不要让你的C ++成为Java只是为了拥有getter和setter - 如果它们实际上没有增加安全性,我真的没有看到使用它们的重点

答案 3 :(得分:0)

要扩展Ben Voight的答案,您可以定义一个代理模板,允许在没有样板的情况下进行此操作:

template <typename Return, typename Containing, Return (Containing::* func)()>
struct proxy
{
   Containing& c;
   proxy(Containing& c) : c(c) {}
   operator Return() { return (c.*func)(); }
   Return& operator=(const Return& r) { return (c.*set)() = r; }
 };

然后定义“属性”

class c {
   int y_;
   int get_y() { std::cout << "Getting y" << std::endl; return y_; }
public:
   proxy<int, x, &x::get_y> y;
   c() : y(*this) {}
};

在客户端代码中

int main() {
   c val;
   val.y = 5;
   std::cout << val.y << std::endl;
}