是否可以将友谊与继承结合起来访问私有数据成员

Posted

技术标签:

【中文标题】是否可以将友谊与继承结合起来访问私有数据成员【英文标题】:Is it ok to combine friendship with inheritance to access private data members 【发布时间】:2011-11-23 12:46:12 【问题描述】:

假设我想要一个类 Child 并且只有这个类从父亲继承 并授予 Child 访问 Fathers 数据成员的权限。除此之外,任何人都不应该从父亲那里继承到它的内部,因此我将父亲的数据保密

编辑:我选择不保护,因为我想隐藏数据。有些人提倡这是一种好的做法,但也许它有点过于教条:(例如 http://drdobbs.com/184403867 中的 Herb Sutter)实际上该课程应该只扩展一次。因此,正如史蒂夫·杰索普(Steve Jessop)所指出的那样,禁止继承是一种选择,但我认为这样做(虚拟等)的成本对于我的需要来说太过分了。

代码如下所示:

class Father
  friend class Child;
  public: 
    //functions
  private:
    int mData;


class Child: public Father
  public:
    void changeData(int val)mData=val;

我在这里遇到了一些严重的麻烦,还是假设继承是一个好的决定,这是一个有效的决定。

【问题讨论】:

如果你真的需要直接访问mDataprotected怎么样? 它闻起来很香,但它可能是个好主意。毕竟,CRTP 是这种模式的一个用例(私有析构函数 + 朋友孩子)。我们肯定需要更多的上下文来讲述。 为什么不直接将changeData 移动到Father 并将mData 设为私有Father?如果Child 直接访问 mData,你就破坏了封装。 问题是您真的想要/需要继承,还是仅出于此处所示的目的使用继承?当你这样做时,它会得到你想要的,只有孩子才能访问父亲的数据。但另一种方法是在父亲中有一个私有成员,您可以从 Child 类(仍然作为朋友)访问它,然后不需要继承。所以我认为你可以在有或没有继承的情况下进行上述操作。另外,朋友是否适用于从 Child 派生的类?我不记得自动取款机了。 @Nedtron 没有朋友不要继承 【参考方案1】:

这实际上并不能阻止其他任何人使用Father 作为基类,它只是阻止他们访问mData(如果他们这样做了)。

如果这就是你想要的(Child 拥有对 Father 的特权访问,而其他类没有,而且 Child 恰好也有一个基类 Father 是不相关的),很好.

如果您另外禁止其他任何人使用Father 作为基类(单独通过文档,或者使用虚拟基类的技巧),那么使用friend 就变得毫无意义了。您不妨将 mData 设为受保护而不是私有,这正是受保护的用途。

【讨论】:

【参考方案2】:

protected: 访问说明符的引入目的完全相同。

虽然这将授予成员对Father所有 Child 的访问权限,但从长远来看,这种设计更简洁且更易于维护。

【讨论】:

我的回答大致相同,但后来意识到 OP 似乎只希望子类可以访问 mData,而使用 protected 可以让任何继承自父亲的类访问它。 @DavidHall,是的,我知道这一点。但是,为了可维护性和良好的编码习惯,将成员设为protected 更为可取。 @iammilind:我认为私有通常比受保护更明智,因为通常不应使用继承来访问基类数据,而是使新类可以通过相同的接口访问。因此主要从抽象类继承以使用多态性【参考方案3】:

如果Child 是唯一应该继承Father 的类,那么您可以在Father 中声明您希望转移到Child 的那些成员和方法(但您仍想保留“来自其他类的机密”)受保护而不是私有。

就像 private 一样,protected 不能从外部访问。

相对于私有,protected 是继承的。

【讨论】:

以上是关于是否可以将友谊与继承结合起来访问私有数据成员的主要内容,如果未能解决你的问题,请参考以下文章

java三大特性封装继承多态

继承对基类私有数据成员的访问(在派生类中继承基类成员函数)

继承 Java 私有成员

回顾C++:访问权限控制之 公有保护私有继承用法详解与总结

子类是不是也继承了 C++ 中的私有数据成员?但是是通过超类的公共方法访问的吗?

5继承与派生2-访问控制