【问题标题】:Friendship and inheritance友谊与传承
【发布时间】:2019-08-19 18:57:52
【问题描述】:

我正在做一个小项目,但我有点卡住了,因为我真的不明白友谊和继承是如何相互作用的。我给你看一些示例代码。

namespace a
{
    class Foo
    {
    public:
        Foo(int x) : m_x(x) {}
    protected:
        friend class b::Derived;
        friend class a::Base;
        int m_x;
    };

    class Base
    {
    public:
        Base(Foo foo) : m_foo(foo) {}
    protected:
        Foo m_foo;
    };
}
namespace b
{
    class Derived : public a::Base
    {
    public:
        Derived(a::Foo foo)
            : Base(foo)
        {
            m_foo.m_x;
        }
    };
}
e0265: at line 29: member a::Foo::m_x (declared at line 10) is inaccessible

显然Derived不能访问Foo的protected成员,貌似是因为Derived::m_foo是派生成员,所以构造Derived会失败。谁能给我详细解释一下?

【问题讨论】:

  • 请发布minimal reproducible example 和完整的编译器错误消息。最可能的问题是您需要将Base() 的实现更改为Base() : m_foo(0) {}
  • Your code works just fine。只有一个问题是 Base::m_foo 需要用 int 初始化。
  • Foo 没有任何私人成员。那么真正的问题是什么?

标签: c++ inheritance friend


【解决方案1】:

显然 Derived 无法访问 Foo 的私有成员,貌似 因为 Derived::m_foo 是派生成员,所以构造 Derived 会失败。

对不起,这不是对朋友的明显误解。

朋友类可以访问任何属性。

您有一个不相关的编码错误... cmets 显示您在 Base 中缺少初始化(Base::m_foo)。修复该问题,向 Foo 添加一些数据项,然后运行您的演示:

#include <iostream>
using std::cout, std::endl; 

class Foo
{
public:
   Foo(int x): m_x(x){}
   ~Foo(){}

   int m_z;   // add public

protected:
   int m_y;   // add protected

private:      // change to private
   friend class Derived;
   int m_x;
};

class Base
{
public:
   Base() : m_foo(0) // add m_foo Initialization (with 0)
      {}
   virtual ~Base(){}
protected:
   Foo m_foo;
};

class Derived : public Base
{
public:
   Derived(Foo foo)
      {
         foo.m_y   = 11;
         foo.m_z   = 22;
         std::cout << foo.m_x << "   "
                   << foo.m_y << "   "
                   << foo.m_z << std::endl;  //friend class can access
      }
};

class T914_t // ctor and dtor compiler provided defaults
{
public:
   int operator()(int argc, char* argv[]) { return exec(argc, argv);  }

private: // methods

   int exec(int , char** )
      {
         Foo     f(99);
         Derived d(f);

         return 0;
      }

}; // class T914_t

int main(int argc, char* argv[]) { return T914_t()(argc, argv); } // call functor

Derived ctor 类访问私有、受保护和公共数据属性的典型输出:

99 11 22

【讨论】:

    【解决方案2】:

    我发现了问题。命名空间 b 以及因此派生的类对 Foo 中的朋友声明不可见。当我转发声明 b 并派生时,一切都按预期工作,派生可以访问私有/受保护成员。

    【讨论】:

      猜你喜欢
      • 2014-07-18
      • 2011-06-16
      • 2013-10-10
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      • 2011-08-24
      • 1970-01-01
      • 2016-05-04
      相关资源
      最近更新 更多