访问与父类是朋友的类的私有成员
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
类具有 bark
和 eat
(以及其他)行为,但您无权访问狗的内部“成员”(例如它有多满)。
@Someprogrammerdude 在我的项目中,一个更好的比喻是满屋子的外科医生(派生类)在为无意识的病人(基类)工作。这真的没有多大意义(为什么它还是派生出来的?)。我现在意识到最好将我的类变成一个数据结构。我希望有一个快速的语法修复,而不是我的程序的完全重组。哦,好吧,你生活和学习
【参考方案1】:
有没有办法说“A是类Base的朋友,都是孩子”
没有。
你可以做的是让基地成为朋友(就像你一样),并在基地中编写一个受保护的访问器,孩子们可以使用它来访问私有成员。
【讨论】:
【参考方案2】:简而言之,c++ 的规则是友谊是不可继承的。 为了实现您的需要,您可以在基类中添加静态受保护方法作为访问器。 但是,如果你真的需要让它没有访问器或吸气剂 你可以使用 reinterpret_cast 来制作,但它会是 hack 并且不推荐。
【讨论】:
是的,正如我在答案中所说,您可以在 Base 类中创建静态保护方法,以访问 Base 的朋友私有数据。但是,如果您将 Base 类的静态受保护方法视为 getter,则除了重新解释强制转换的技巧之外别无他法 @Trad_NotSuitedPC 您可以使用公共成员作为替代。或者在 A 中添加公共 setter 和 getter @Trad_NotSuitedPCreinterpret_cast
“有效”没有“技巧”。 reinterpret_cast
有一些有效的用途,然后是“技巧”,即编译器会让你做的事情,但在形式上是无稽之谈。不应在任何实际代码中使用后者。
@Trad_NotSuitedPC 好吧,对于重新解释转换,您需要创建另一个类 A1 对感兴趣的数据成员具有公共访问权限,并且在任何其他意义上与 A 类相同,然后将指向 A 的转换指针重新解释为指针到 A1,然后如果指向 A1 的指针非 nullptr,则使用数据。但是,同样,不推荐使用 c++ 的方式
@Trad_NotSuitedPC 除了完全不可移植之外,它也是狡猾和愚蠢的。请写好代码,不需要“技巧”。【参考方案3】:
有没有办法说“A是类Base的朋友,都是孩子”
没有
您需要修复您的设计。不应授予类访问从基类派生的所有类型的成员的权限。根据您的代码,我认为您需要在其他类的构造函数中修改一个类的私有成员。
一种可能的解决方案是使用参数化构造函数。您可以从类Base
和Derived
中调用类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 函数。 我明确要求不提供解决方案以上是关于访问与父类是朋友的类的私有成员的主要内容,如果未能解决你的问题,请参考以下文章