关于来自 VC12 和 VC14 的 c++ 友谊和继承的不同行为
Different behavior about c++ Friendship and inheritance from VC12 and VC14
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.aspx or http://en.cppreference.com/w/cpp/language/friend 看来友谊是不可传递的,不能继承。但是我认为这个代码示例并非如此。
但为什么 VC14 不会给我报错?
如果 VC14 是正确的,我怎样才能 "modify" 代码使 VC12 也可以呢?
在 class Derived?
中再次定义受保护的 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();
}
};
另一种可能的解决方法(使用基于密钥的访问)
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());
}
};
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.aspx or http://en.cppreference.com/w/cpp/language/friend 看来友谊是不可传递的,不能继承。但是我认为这个代码示例并非如此。
但为什么 VC14 不会给我报错?
如果 VC14 是正确的,我怎样才能 "modify" 代码使 VC12 也可以呢? 在 class Derived?
中再次定义受保护的 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();
}
};
另一种可能的解决方法(使用基于密钥的访问)
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());
}
};