我有以下代码:
struct A {
protected:
A() {}
A* a;
};
struct B : A {
protected:
B() { b.a = &b; }
A b;
};
奇怪的是没有编译。罪魁祸首是b.a = &b;
任务:GCC和clang都抱怨A()
受到保护,这应该不是问题,因为B继承了A.我进入标准的哪个黑暗角落?
答案 0 :(得分:21)
protected
的含义是派生类型可以访问其自己的基础的成员,而不能访问任何随机对象 * 。在您的情况下,您需要尝试修改b
无法控制的成员(即您可以设置this->a
,但不能设置b.a
)
如果你感兴趣的话,有一个hack可以让它工作,但更好的解决方案是重构代码而不依赖于hacks。例如,您可以在A
中提供一个构造函数,该构造函数将A*
作为参数(此构造函数应该是公共的),然后在B
的初始化列表中初始化它:
A::A( A* p ) : a(p) {}
B::B() : b(&b) {}
* protected
授予您在自己类型的任何实例中访问基本成员或从您自己的类型派生的权限。
答案 1 :(得分:2)
这里实际上有两个不同的问题。
第一个是该行不仅仅进行赋值,而是尝试初始化基类(工作正常)和成员b
。要创建b
成员,需要构建它,作为成员需要public
访问构造函数,而它没有。
然后,分配也无法访问b
的非公开成员,因为它不是B
类型,而是键入A
。
请注意,protected
表示您只能通过A
对象(或儿童)访问B
的部分内容。
在这种情况下,请告诉我们您的真正问题,我们可以尝试帮助解决它。从同一类型继承和创作是一种设计气味。
答案 2 :(得分:0)
我测试的所有编译器都抱怨了几件事情,特别是受保护的构造函数会出现问题,即使删除了赋值语句。
您无法访问您派生的任何类型实例的protected
成员。这个问题在11.4p1的例子中得到澄清。
class B {
protected:
int i;
static int j;
};
class D1 : public B {
};
class D2 : public B {
void mem(B*, D1*);
};
void D2::mem(B* pb, D1* p1) {
pb->i = 1; // ill-formed
p1->i = 2; // ill-formed
// ...
}
答案 3 :(得分:0)
这似乎是C ++语言的一个很大的局限。你会如何解决这样的问题:
class Node
{
public:
void Save();
protected:
virtual void SaveState(int type) = 0;
};
class BinaryNode : public Node
{
protected:
Node *left;
Node *right;
virtual void SaveState(int type) override
{
left->SaveState(type);
right->SaveState(type);
}
};
在此示例中,我不希望方法SaveState
在Node
层次结构之外可见。只有方法Save
应为public
。