访问与父类是朋友的类的私有成员

Posted

技术标签:

【中文标题】访问与父类是朋友的类的私有成员【英文标题】:Access private members of class that is friends with parent class 【发布时间】:2020-06-15 11:10:41 【问题描述】:

考虑以下

class Base;

class A 
  int x;

  friend class Base;
;

class Base 
  protected:
    A a_obj;

  public:
    Base()
      a_obj.x; // works
    
;

class Derived : public Base 
  public:
    Derived()
      a_obj.x; // not accessible
    
;

我可以公开 x 的 getter 和 setter,或者公开对象,但这不是可取的。假设有一堆派生类,在class A 中添加friend class Derived 会使代码过于冗长。有没有办法说“A 是 Base 类的朋友,都是孩子”

【问题讨论】:

不,没有办法写出这样的朋友声明。一个朋友明确地只针对提到的类。另一方面,我认为您需要重新考虑您的设计,而不是使用直接的名词到类的翻译,而是考虑所需对象的行为。因此,例如,您无需尝试直接获取 x 的值,而是要求 a_obj 对象执行操作并从该操作中获取结果。 您的设计需要修复。不应授予类访问从一个基派生的所有类型的成员。这些成员应该是基地的(受保护的)成员 @Someprogrammerdude 这就是我会做的。在这个例子中,“重新考虑设计”似乎很明显,但这只是我正在研究的一个提炼版本。在我的示例中,按照您的建议制作 getter 和 setter 是不明智的。有没有一种不冗长的替代友谊可以允许这样做? 不,我不是指简单的 getter 或 setter,这就像使用 friend 或将成员全部设为 public。相反,我的意思是调用a_obj 的成员函数来执行动作,进行一些计算或其他类似的事情,然后返回结果。不要将类视为简单的容器或成员分组,应将它们视为某种行为。例如,Dog 类具有 barkeat(以及其他)行为,但您无权访问狗的内部“成员”(例如它有多满)。 @Someprogrammerdude 在我的项目中,一个更好的比喻是满屋子的外科医生(派生类)在为无意识的病人(基类)工作。这真的没有多大意义(为什么它还是派生出来的?)。我现在意识到最好将我的类变成一个数据结构。我希望有一个快速的语法修复,而不是我的程序的完全重组。哦,好吧,你生活和学习 【参考方案1】:

有没有办法说“A是类Base的朋友,都是孩子”

没有。

可以做的是让基地成为朋友(就像你一样),并在基地中编写一个受保护的访问器,孩子们可以使用它来访问私有成员。

【讨论】:

【参考方案2】:

简而言之,c++ 的规则是友谊是不可继承的。 为了实现您的需要,您可以在基类中添加静态受保护方法作为访问器。 但是,如果你真的需要让它没有访问器或吸气剂 你可以使用 reinterpret_cast 来制作,但它会是 hack 并且不推荐。

【讨论】:

是的,正如我在答案中所说,您可以在 Base 类中创建静态保护方法,以访问 Base 的朋友私有数据。但是,如果您将 Base 类的静态受保护方法视为 getter,则除了重新解释强制转换的技巧之外别无他法 @Trad_NotSuitedPC 您可以使用公共成员作为替代。或者在 A 中添加公共 setter 和 getter @Trad_NotSuitedPC reinterpret_cast“有效”没有“技巧”。 reinterpret_cast 有一些有效的用途,然后是“技巧”,即编译器会让你做的事情,但在形式上是无稽之谈。不应在任何实际代码中使用后者。 @Trad_NotSuitedPC 好吧,对于重新解释转换,您需要创建另一个类 A1 对感兴趣的数据成员具有公共访问权限,并且在任何其他意义上与 A 类相同,然后将指向 A 的转换指针重新解释为指针到 A1,然后如果指向 A1 的指针非 nullptr,则使用数据。但是,同样,不推荐使用 c++ 的方式 @Trad_NotSuitedPC 除了完全不可移植之外,它也是狡猾和愚蠢的。请写好代码,不需要“技巧”。【参考方案3】:

有没有办法说“A是类Base的朋友,都是孩子”

没有

您需要修复您的设计。不应授予类访问从基类派生的所有类型的成员的权限。根据您的代码,我认为您需要在其他类的构造函数中修改一个类的私有成员。

一种可能的解决方案是使用参数化构造函数。您可以从类BaseDerived 中调用类A 的构造函数。

class Base;

class A 
  int x;

public:
  A(int in): x(in)
  

  

;

class Base 
protected:
    A a_obj;

public:
    Base(int in): A(in)
    

    
;

class Derived : public Base 
public:
    Derived(): Base(5)
    

    
;

【讨论】:

这不是我问的。这仍然使 a_obj 在 Derived 类中无法访问。 为此,您可以使用 setter 和 getter 函数。 我明确要求不提供解决方案

以上是关于访问与父类是朋友的类的私有成员的主要内容,如果未能解决你的问题,请参考以下文章

Java基础随记

急急急!!!!C# 中关于子类访问基类成员的可访问性

继承和接口

通过反射访问父类的私有成员

Java子类访问父类的私有成员变量

C++ 类的继承一(访问控制)