我们有两个班级(A和B)。 A类只能由从中继承的类创建(A类) 和B类可以由用户创建。
A类,版本1有一个私有数据成员,并且有方法来接收A类数据。
A类,版本2有一个受保护的数据成员,因此,对于将继承自该类以接收A类数据的类,不需要任何方法
A类,第1版
class A
{
protected:
A() = default;
void set_data( T d );
T& get_data();
private:
T data;
}
A类,第2版
class A
{
protected:
A() = default;
T data;
}
B类
class B : public A {}
哪个版本的A类是首选版本?
答案 0 :(得分:2)
这是相当主观的,但我会说95%的时间都不是。受保护的数据使您的代码与公共代码一样难以维护,因此我们立即对该版本进行了规则。但是你也几乎不需要直接的mutator(set)函数,因此我们将切断该函数,然后将get函数的签名更改为const T& get_data() const;
。然后我们将向父级添加一个真正的接口来操纵它的状态,而不是让外部的东西决定新状态应该是什么。
答案 1 :(得分:0)
如果您遵循通用准则,则数据成员应该是私有的。因此,版本1是优选的。另一方面,在我看来,完全琐碎的get / set对是一个次要的代码气味,所以你可能想要调查为什么该成员首先需要完全暴露给派生类。
答案 2 :(得分:0)
如果您需要除了对变量的简单访问之外的任何其他内容,请使用访问器函数:验证值,维护类不变量,发送信号更改,记录等。请注意get
应返回值或{{1参考;您的版本,返回非const引用,可用于为变量分配任意值,绕过const
函数。
如果您只需要简单访问,那么为了简单起见,有人会建议公开变量;其他人会建议使用访问器函数以保持一致性(与需要此类事物的其他类型)或向后兼容性(如果您以后决定需要函数)。没有令人信服的理由更喜欢这两种选择。
答案 3 :(得分:0)
您的第一版始终是首选。默认情况下,类的数据成员应为private
。使数据成员全部公开仅在一种情况下是合理的,即如果您只想捆绑数据。只有这样,您才会使用struct
并公开所有数据。 (想捕捉链表中单个节点的本质)
但是,protected
的情况下没有这种例外。您始终可以将它们设为私有,并为这些数据成员提供访问者/变更器。
public
数据成员的缺点是他们打破了封装。并且很难维护不变量,因为数据可以从各方面进行修改。 protected
数据成员的情况比public
略有限制,因为它只通过派生类成员和朋友开辟了修改方式。但它仍然打破了封装。
结论: - 类的所有数据成员应始终为private
,除非它打算用作bundle-o-data
。
除此之外,您永远不会像以前那样将句柄传递给外部用户: -
T& get_data();
所以,更好的方法是
const T& get_data();
除了某些特定情况外。