2016-09-21 36 views
5
class Base 
{ 
protected: 
    void func1(); 
}; 

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

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

我可以编译VCl 4码(Visual Studio的2015)全无错误 但VC12得到错误(Visual Studio的2013年)不同的行为有关从VC12 C++的友谊和继承的VCl 4

cannot access protected member declared in class 'Base' 

谁是对的? 这种与继承有关的freindship的正确性是什么?

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

但是为什么VC14不会给我一个错误?

如果VC14是正确的,我该如何“修改”代码,以便VC12也可以吗? 在派生类中再次定义受保护的func1()

+0

我怀疑你可以编译任何编译器代码:它缺少一些分号。 – rubenvb

+0

GCC http://ideone.com/Zue7WL没有错误。 –

+0

好问题。传递性和继承不适用,因为它是将Third声明为朋友的派生类。代码被clang和gcc接受。 – drRobertz

回答

4

固定错别字后,评论在线:

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

VCl 4是正确的。

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

@songyuanyao我的意思是说,它是私人的,因为另一个类在 –

+0

@juanchopanza纠正。 –

+0

@songyuanyao纠正。谢谢。 –