【问题标题】:Different behavior about c++ Friendship and inheritance from VC12 and VC14关于 c++ Friendship 和从 VC12 和 VC14 继承的不同行为
【发布时间】:2017-01-29 09:58:19
【问题描述】:
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()?

【问题讨论】:

  • 我怀疑你可以在任何编译器上编译该代码:它缺少一些分号。
  • 在 GCC ideone.com/Zue7WL 上没有错误。
  • 好问题。传递性和继承不适用,因为它是派生类将 Third 声明为友元。该代码被 clang 和 gcc 接受。

标签: c++ visual-studio inheritance friend


【解决方案1】:

修正错别字后,cmets inline:

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();
     }
};

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

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());
     }
};

【讨论】:

  • @songyuanyao 我的意思是说它是私有的,只要另一个班级在看
  • 谢谢!!那么保持 func1 受保护并让 VC12 也满意的最小方法是什么?
  • @elgcom 我原以为在Derived 中可以写protected: using Base::func1; 将名称注入Derived 命名空间。
  • 我喜欢受保护的“解决方法”:使用 Base::func1;
  • Re: "// 受保护的可见性" -- publicprotectedprivate 是关于访问,而不是可见性 .私有名称和受保护名称在任何地方都可见,但私有名称和受保护名称仅在有限的上下文中可访问
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 2015-01-02
  • 2012-11-08
  • 2011-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多