【问题标题】:making public member read only使公共成员只读
【发布时间】:2016-01-20 17:12:38
【问题描述】:
class A{
    private:
        int a;
    public:
        const int &ref = a;
};

int main() {
    A obj;
    obj.a = 20;     // error cause private
    obj.ref = 30;   // not private but const so ERROR
    return 0;
}

我正在尝试使成员变量可访问但只能通过接口读取。目前我已经尝试过这种方法,它似乎编译得很好。我为我的原始变量int a 做了一个const reference 并把它变成了public。这种做法有什么问题我可能会错过吗?或者这个例子是否安全可靠地用于实际目的?

提供具有const 正确性的成员函数没有错(我也使用过它并打算一直这样做),但我问如果我必须提供这种方式有什么问题一个只读变量。

谢谢你:)

【问题讨论】:

  • 好旧的访问器函数有什么问题? int A::get_a() const noexcept { return this->a; }
  • 更好的做法是使用 getter 和 setter 来访问你的类成员。您可以更好地控制访问逻辑
  • 不为类添加const int&成员中断复制语义吗?
  • @JamesAdkison 你能解释一下吗...
  • @JamesAdkison 重点(另一点是增加班级规模,不必要)

标签: c++ oop c++11


【解决方案1】:
class A{
    private:
        int a;
    public:
        const int &ref = a;
};

如果我必须提供一个只读的变量,这种方式有什么问题吗

对于 A 类的这种设计决策至少有几个缺点。

1:班级规模

正如Dieter Lückingcomment:

不必要地增加类的大小

2:复制语义

它破坏了编译器生成的复制赋值运算符。例如,以下代码行为通常是可取的,但不起作用。

A obj1;

// ...

A obj2;

// make changes to 'obj2'

// Update 'obj1' with the changes from 'obj2'
obj1 = obj2; // This copy doesn't work!

更多信息:

使用引用有一定的规则:

  1. 引用必须在创建时进行初始化。 (指针可以随时初始化。)
  2. 一旦一个对象的引用被初始化,就不能改变它来引用另一个对象。 (指针可以随时指向另一个对象。)
  3. 您不能有 NULL 引用。您必须始终能够假定引用连接到合法的存储。

可以实现自定义赋值运算符,但需要维护更多代码(即,我认为的另一个缺点)。

#include <iostream>

class A
{
private:
    int a;

public:
    explicit A(int value) : a(value) {}

    A& operator=(const A& other)
    {
        a = other.a;
        return *this;
    }

    const int& ref = a;
};

int main()
{
    A obj1(10);
    std::cout << "1: " << obj1.ref << "\n";

    A obj2(20);
    std::cout << "2: " << obj2.ref << "\n";

    obj1 = obj2;
    std::cout << "1: " << obj1.ref << "\n";

    return 0;
}

解决此问题的惯用方法是使用适当的访问器函数。

class A {
    private:
        int a;

    public:
        int getA() const { return a; }
};

【讨论】:

  • 我刚试过 ideone 和 found 确实复制语义会被破坏。你也能包括原因吗?或者我应该为他们发布另一个问题?谢谢:)
  • @oopaewem 我更新了答案并提供了一些额外的参考资料。
  • it may be possible to implement a custom assignment operator: 不,这是不可能的(只有当引用是指针时才有可能,但又丑陋了)
  • @DieterLücking 我也不认为这是可能的,但我尝试了following,它似乎工作正常(即,自定义赋值运算符忽略了const int&amp; 数据成员)。我已从我的回答中删除了该评论,但我很好奇为什么我的示例代码似乎有效?
  • @James Adkison 我错了(我在考虑非内部参考)。这也使答案错误
【解决方案2】:

在 C++ 中执行此操作的标准方法是创建实际成员 private,但包括接口的公共“getter”方法,如下所示:

class A{
    private:
        int a;
    public:
        int get_a() const { return a; }

        A() : a(20) {}
};

int main() {
    A obj;
    int n = obj.get_a(); // n = 20
    return 0;
}

用户无法设置A::a的值,但可以使用A::get_a检索其值。

【讨论】:

  • int get_a() const;
  • 构造函数的初始化列表会更好
猜你喜欢
  • 2016-11-23
  • 1970-01-01
  • 2012-11-24
  • 2017-05-28
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
相关资源
最近更新 更多