21

我有以下代码:

struct A {
protected:
    A() {}

    A* a;
};

struct B : A {
protected:
    B() { b.a = &b; }

    A b;
};

它奇怪地不编译。罪魁祸首是b.a = &b;任务:GCC和clang都抱怨A()受到保护,这不应该是问题,因为B继承了A。我进入了标准的哪个黑暗角落?

4

4 回答 4

21

的含义protected是派生类型将可以访问其自身基类的成员,而不是任何随机对象*。在您的情况下,您关心尝试修改b您无法控制的成员(即您可以设置this->a,但不能设置b.a

如果您有兴趣,有一个 hack 可以让它工作,但更好的解决方案是重构代码而不依赖于 hack。例如,您可以提供一个构造函数,A其中接受一个A*as 参数(此构造函数应该是公共的),然后在初始化列表中对其进行初始化B

A::A( A* p ) : a(p) {}
B::B() : b(&b) {}

* protected授予您访问您自己类型的任何实例或从您自己的类型派生的基本成员的权限。

于 2012-09-04T20:38:00.640 回答
2

这里实际上有两个不同的问题。

首先是该行不只是进行赋值,而是尝试初始化基类(工作正常)和成员b。要创建b成员,它需要构造它,并且作为成员,它需要public访问它没有的构造函数。

然后分配也无法访问非公共成员,b因为再次,它不是类型B而是类型A

请记住,这意味着您只能通过对象(或子对象)protected访问部分内容。A B

在这种情况下,请告诉我们您的真正问题,我们可以尝试帮助解决它。从同一个类型继承和组合是一种设计气味。

于 2012-09-04T20:42:19.887 回答
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
  // ...
}
于 2012-09-04T20:40:53.210 回答
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

于 2014-09-09T09:45:36.863 回答