c++ - 关于来自 VC12 和 VC14 的 c++ 友元和继承的不同行为

标签 c++ visual-studio inheritance friend

class Base 
{
protected:
    void func1();
};

class Derived : public Base
{
friend class Third;
};

class Third
{
     void foo() 
     {
        Derive d;
        d.func1();
     }
};

我可以在 VC14 (Visual Studio 2015) 中编译代码而不会出错 但从 VC12 (Visual Studio 2013) 得到错误

cannot access protected member declared in class 'Base'

谁是对的? 这种具有继承性的友元的正确性是什么?

来自 MSDN https://msdn.microsoft.com/en-us/library/465sdshe.aspxhttp://en.cppreference.com/w/cpp/language/friend看来友元是不可传递的,不能继承的。但是我认为这个代码示例并非如此。

但为什么 VC14 不会给我报错?

如果 VC14 是正确的,我如何“修改”代码以便 VC12 也可以呢? 在 Derived 类中再次定义 protected func1()?

最佳答案

修正拼写错误后,内联评论:

class Base 
{
protected:
    void func1();   // protected access
};

class Derived : public Base
{
  // implicit protected func1, derived from Base

  // this means 'make all my protected and private names available to Third'
  friend class Third;
};

class Third
{
     void foo() 
     {
        Derived d;
        // func1 is a protected name of Derived, but we are Derived's friend
        // we can therefore access every member of Derived
        d.func1();
     }
};

VC14 是正确的。

VC12 的可能解决方法:

class Base 
{
protected:
    void func1();
};

class Derived : public Base
{
  protected:
    using Base::func1;

  private:
    friend class Third;
};


class Third
{
     void foo() 
     {
        Derived d;
        d.func1();
     }
};

另一种可能的解决方法(使用基于 key 的访问)

class Third;
class Func1Key
{
  private:
    Func1Key() = default;
    friend Third;
};

class Base 
{
protected:
    void func1();
};

class Derived : public Base
{
public:  
  void func1(Func1Key) 
  {
    Base::func1();
  }
};


class Third
{
     void foo() 
     {
        Derived d;
        d.func1(Func1Key());
     }
};

关于c++ - 关于来自 VC12 和 VC14 的 c++ 友元和继承的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39611665/

相关文章:

c++ - 显示器之间的Qt自定义无框窗口中的绘画问题

c++ - boost 多索引私有(private)成员访问

c# - 无法将 "C:\Windows\System32\shdocvw.dll"添加到我的项目中

c++ - 有没有需要多重继承的场景?

c#在方法的参数中继承一个带有派生类的接口(interface)

android - 如何在 Qt/QML for android 中创建网页缩略图

c++ - 指针运算 : *p++ and (*p)++ and more

c++ - 在控制台应用程序中使用 GDI+

c++ - WinInet 未定义标识符

c# - 将类的现有实例转换为更具体的子类