访问友元类的私有成员,该友元类是父类

3

考虑以下内容

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,或者将对象设为public,但这并不是首选。假设有一堆派生类,将friend class Derived添加到class A中会使代码过于冗长。是否有一种方法来表示"A与Base类及其所有子类为好友关系"?


1
没有办法编写这样的友元声明。友元只是明确为特定类服务的。另外,我认为您需要重新考虑设计,而不是直接将名词翻译为类,而是思考所需对象的行为。例如,您可以要求a_obj对象执行某个操作并从该操作中获取结果,而不是直接获取x的值。 - Some programmer dude
1
你的设计需要修正。类不应该被授予访问从一个基类派生的所有类型成员的权限。这些成员应该是基类的(protected)成员。 - 463035818_is_not_a_number
@Someprogrammerdude 这就是我会做的。在这个例子中,重新考虑设计似乎是显而易见的,但这只是我正在处理的问题的精简版本。在我的例子中,按照你的建议制作getter和setter并不明智。有没有一种非冗长的友谊替代方案可以实现这一点? - Trad_NotSuitedPC
2
不,我不是指简单的getter或setter,那就像使用“friend”或使成员全部为“public”。相反,我的意思是调用a_obj的成员函数执行操作,进行一些计算或其他类似的事情,然后返回结果。不要把类看作简单的容器或成员分组,而是根据某种行为来考虑它们。例如,一个“狗”类有“吠叫”和“进食”(还有其他行为),但您无法访问狗的内部“成员”(例如它有多饱)。 - Some programmer dude
@Someprogrammerdude 在我的项目中,更好的比喻是一个充满外科医生(派生类)在为一个失去意识的患者(基类)进行手术。这并不是很有意义(为什么它要派生呢?)。我现在意识到最好将我的类变成一个数据结构。我希望有一个快速的语法修复方法,而不是完全重构我的程序。哦,好吧,你活着就会学习。 - Trad_NotSuitedPC
3个回答

4

有没有一种方法可以说“A与类Base及其所有子类是朋友”?

没有。

你可以让Base成为一个友元(如你所做的),并在Base中编写一个受保护的访问器,使子类可以使用它来访问私有成员。


3
简而言之,C++ 规则是友元不可继承。为了达到您的需求,您可以在基类中添加静态受保护方法作为访问器。但是,如果您真的需要在没有访问器或 getter 的情况下实现它,您可以通过 reinterpret_cast 来实现,但这是一种 hack 方法,不建议使用。

1
是的,正如我在答案中所述,您可以在基类中创建静态受保护方法,以访问基类的友元私有数据。但是,如果您将基类的静态受保护方法视为getter,则除了使用reinterpret cast技巧外,没有其他方法。 - Boki
1
@Trad_NotSuitedPC 你可以使用公共成员作为替代方案。或者在A中添加公共setter和getter方法。 - armagedescu
1
@Trad_NotSuitedPC reinterpret_cast 没有任何“技巧”可言。reinterpret_cast 有一些有效的使用场景,但也有一些“技巧”,即编译器允许你这样做,但在形式上是无意义的。在任何真实的代码中都不应该使用后者。 - underscore_d
1
@Trad_NotSuitedPC 嗯,对于reinterpret_cast,您需要创建另一个名为A1的类,并具有与类A相同的公共访问权限以访问感兴趣的数据成员。然后将指向A的指针重新解释为指向A1的指针,如果指向A1的指针非nullptr,则可以使用数据。但是,再次强调,这不是推荐使用C++的方式。 - Boki
1
@Trad_NotSuitedPC 除了完全不可移植之外,它还是狡猾和愚蠢的。请编写不需要“技巧”的好代码。 - underscore_d
显示剩余5条评论

1

有没有一种方法可以说“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)
    {

    }
};

这不是我要求的。这仍然使得类Derived中的a_obj无法访问。 - Trad_NotSuitedPC
1
为此,您可以拥有设置器和获取器函数。 - abhiarora
我明确要求不提供解决方案。 - Trad_NotSuitedPC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接