7

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

“BaseTest::_protMember”:无法访问在“BaseTest”类中​​声明的受保护成员

为什么我不能访问_protMembermy 中的成员变量,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
    };
};

后续问题:

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

4

3 回答 3

11

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

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

后续问题:为什么在添加的复制构造函数中我可以访问另一个实例的受保护成员?

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并禁止任何派生类使用它。

于 2013-07-18T07:23:39.207 回答
6

您只能访问protected类实例中的成员。那是 :

class SubTest : public BaseTest
{
    SubTest(const BaseTest &baseTest)
    {
        _protMember = baseTest._protMember;
     // ^^^^^^^^^^^ Is good because you are in the instance of its class
        _protMember = baseTest._protMember;
     //               ^^^^^^^^^^^^^^^^^^^^^ Produce error because you are not in the baseTest instance.              
    };

    // followup question
    SubTest(const SubTest &subTest)
    {
        _protMember = subTest._protMember;
      // Compile because access modifiers work on class level, and not on object level.
    };
};

编辑后续行动:

访问修饰符作用于类级别,而不是对象级别。

也就是说,同一类的两个对象可以访问彼此的私有成员。

这是我的来源:为什么我可以在复制构造函数中访问私有变量?

于 2013-07-18T07:27:03.073 回答
0

通过定义_protMemberasprotected您允许派生类的对象访问它们自己的 _protMember. 这并不意味着派生类的所有对象都可以访问_protMember其他对象。

于 2013-07-18T07:25:47.623 回答