【发布时间】:2019-10-16 04:49:03
【问题描述】:
我发现了一种奇怪的方法来破坏类中派生类的封装
采取以下措施
class Base
{
private:
class Member
{
public:
virtual ~Member() {}
virtual void Function() = 0;
};
};
如果你尝试从这个私有类派生
class DerivedMember : public Base::Member
{
public:
DerivedMember() {}
virtual void Function() {/*Do something*/}
};
你得到一个编译错误
error: 'class Base::Member' is private
error: within this context
但是如果你从它派生一个模板
template <typename T>
class TemplateDerivedMember : public Base::Member
{
public:
TemplateDerivedMember () {}
virtual void Function() {/*Do something*/}
};
然后编译器将接受它,并允许这种情况发生。
我已经针对 GCC 8.1 和 GCC 4.6 对此进行了测试,两者的行为相同。
这是一个错误,还是应该允许的?将其作为模板类派生是否隐含地将TemplateDerivedMember 类作为Base 的成员? (它似乎无法在全局命名空间中访问)
【问题讨论】:
-
似乎是 gcc 的一个错误:无论模板是否被实例化,它都接受代码。有趣的是,无论模板是否实例化,Clang 都会拒绝,而 MSVC 仅在实例化时才会拒绝。神箭:godbolt.org/z/t2nI14
-
还有其他方法可以通过模板打破访问控制;这有关系吗?
-
它可能不是唯一的,但这取决于它是否是一个错误,而不是 UB,或者一个定义的方法来破坏它。如果编译器以不同的方式实现它,它可能不是标准化的东西,甚至不是标准的一部分。