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