以下代码产生编译器错误:



为什么我不能访问我的 _protMember 中的成员变量 class SubTest 即使它受到保护?

class BaseTest
{
public:
    BaseTest(){};

    BaseTest(int prot)
    {
        _protMember = prot;
    };

protected:
    int _protMember;
};

class SubTest : public BaseTest
{
    // followup question
    SubTest(const SubTest &subTest)
    {
        _protMember = subTest._protMember; // this line compiles without error
    };

    SubTest(const BaseTest &baseTest)
    {
        _protMember = baseTest._protMember; // this line produces the error
    };
};

后续问题:

为什么在添加的复制构造函数 中我可以访问另一个实例的 protected 成员

最佳答案

您只能从您自己的基类实例访问 protected 成员......而不是作为参数提供给您的成员。这真的是关于 OO 封装的。如果没有这个限制,正在构建的对象可能会使 baseTest& 参数的不变量无效。

换句话说,您的 SubTest 可能决定使用 protected 成员,该成员与另一个 BaseTest 派生类(例如 SubTest2 : BaseTest )对同一成员的使用相冲突。如果您的 SubTest 代码被允许摆弄其他对象的数据,它可能会使 SubTest2 对象中的不变量无效,或者获取一些值 - 在预期的封装中 - 仅意味着暴露给 SubTest2 和(可选 - 见下文) SubTest2 衍生物。


SubTest(const SubTest& x);  // can access x._protMember
SubTest(const BaseTest& x);  // cannot access x._protMember

上面相同的见解解释了为什么允许这样做:复制构造函数获得 SubTest& 而不仅仅是从 BaseTest 派生的任何旧对象,并且这个构造函数显然在 SubTest 抽象中。 SubTest 编码器被假定为熟悉 SubTest 提供的预期设计/封装,并且复制构造函数也被授予绕过和强制其他 SubTest& 对象的后置条件/不变量的访问权限。 (您正在从一个对象复制,该对象本身可能是由相同的函数复制构造的,因此在“*this”端保护它而不是参数引用端根本没有太多保护,甚至忽略您可能想要/需要该访问权限的所有合理原因)。
SubTest 派生对象可能会被意外传递给 SubTest 复制构造函数(“切片”),但即使在这种情况下,SubTest& 类也可以控制进一步派生的对象是否可以使用 _protMember 执行任何意外 - 添加private using BaseTest::_protMember; 语句,如果它想“完成”对 _protMember 的访问并禁止任何派生类使用它。

10-08 11:55