我很困惑:我认为受保护的数据是由C ++中给定类的子进程读/写的。
以下代码段无法在MS Compiler中编译
class A
{
protected:
int data;
};
class B : public A
{
public:
B(A &a)
{
data = a.data;
}
};
int main()
{
A a;
B b = a;
return 0;
}
错误信息:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
demoFail.cpp
demoFail.cpp(12) : error C2248: 'A::data' : cannot access protected member declared in class 'A'
demoFail.cpp(4) : see declaration of 'A::data'
demoFail.cpp(2) : see declaration of 'A'
我究竟做错了什么?
根据TC ++ PL,第404页:
派生类只能为其自身类型的对象访问基类'受保护成员....这可以防止在一个派生类破坏属于其他派生类的数据时可能发生的细微错误。
当然,这是一个简单的方法来解决这个问题:
class A
{
protected:
int data;
};
class B : public A
{
public:
B(const A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}
根据TC ++ PL,第404页:
派生类只能为其自身类型的对象访问基类'受保护成员....这可以防止在一个派生类破坏属于其他派生类的数据时可能发生的细微错误。
当然,这是一个简单的方法来解决这个问题:
class A
{
protected:
int data;
};
class B : public A
{
public:
B(const A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}
C ++标准说明了受保护的非静态成员 11.5/1
当派生类的朋友或成员函数引用受保护的非静态成员函数或受保护的基类的非静态数据成员时,除了前面第11章中描述的那些之外,还应用访问检查。除非形成指向成员的指针(5.3) .1),访问必须通过指向,引用或派生类本身的对象(或从该类派生的任何类)(5.2.5)。如果访问要形成指向成员的指针,则nested-name-specifier应命名派生类(或从该类派生的任何类)。
除了修复其他人之前提到的东西(构造函数) B
是私人的),我认为rlbond的方式会做得很好。但是,标准的上一段的直接后果是使用成员指针可能会出现以下情况,当然可能是类型系统中的一个洞,当然
class B : public A {
public:
B(A &a){
int A::*dataptr = &B::data;
data = a.*dataptr;
}
};
当然,不建议使用此代码,但会显示您 能够 访问它,如果你真的需要(我已经看到这种方式用于打印出来的 std::stack
, std::queue
, std::priority_queue
通过访问其受保护的容器成员 c
)
你刚才 不能 复制一份 A
对象 B
构造函数。目的是离开初始化 A
它的成员是它自己的构造函数:
struct A {
A( const A& a ): data( a.data ) {}
protected: int data;
};
struct B : public A {
B( const A& a ): A( a ) {}
};
B的构造函数是私有的。如果未在类中指定任何内容,则默认修饰符为private(对于结构,它是公共的)。所以在这个例子中问题是你不能构造B.当你向构造函数B添加public时,会出现anoter问题:
在这种情况下,B有权修改它所衍生的A部分而不是另一部分。
你可以这样做:
class A
{
public:
A()
: data(0)
{
}
A(A &a)
{
data = a.data;
}
protected:
int data;
};
class B : public A
{
public:
B(A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}