以下代码会产生编译错误:
'BaseTest :: _ protMember':无法访问声明的受保护成员 class'BaseTest'
为什么我无法访问_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
};
};
后续问题:
为什么在添加的复制构造函数中我可以访问另一个实例的受保护成员?
答案 0 :(得分:11)
您只能从您自己的基类实例访问protected
成员...而不是作为参数提供给您的成员。这完全是关于OO封装的。如果没有此限制,正在构造的对象可能会使baseTest&
参数的不变量无效。
换句话说,您的SubTest
可能决定某个protected
成员的使用与另一个BaseTest
派生类的同一成员的使用冲突(例如{{} 1}})。如果允许你的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;
语句使用它。
答案 1 :(得分: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.
};
};
后续编辑:
访问修饰符适用于类级别,而不适用于对象级别。
也就是说,同一个类的两个对象可以访问彼此的私有成员。
这是我的来源:Why can I access private variables in the copy constructor?
答案 2 :(得分:0)
通过将_protMember
定义为protected
,您可以允许派生类的对象访问他们自己的 _protMember
。这并不意味着派生类的所有对象都可以访问其他对象的_protMember
。