【问题标题】:Template class derived from private member class breaks encapsulation从私有成员类派生的模板类打破了封装
【发布时间】: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,或者一个定义的方法来破坏它。如果编译器以不同的方式实现它,它可能不是标准化的东西,甚至不是标准的一部分。
  • @KaenbyouRin:有小的变化,他们都在等待实例化Demo(但gcc仍然接受它Demo

标签: c++ templates gcc


【解决方案1】:

是的,这是一个错误,显然自 GCC 11 以来已修复。据我所知,Clang 和 MSVC 总是拒绝该代码。演示:https://gcc.godbolt.org/z/9evfYq5hc

【讨论】:

    猜你喜欢
    • 2021-07-25
    • 1970-01-01
    • 2023-03-18
    • 2017-11-27
    • 2017-04-14
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 2013-02-18
    相关资源
    最近更新 更多