Невозможно получить доступ к защищенному члену базового класса в производном классе

У меня есть следующий код:

struct A {
protected:
A() {}

A* a;
};

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

A b;
};

Это странно не компилируется. Виновником является b.a = &b; назначение: и GCC, и Clang жалуются, что A() защищен, что не должно быть проблемой, потому что B наследует A. В какой темный угол стандарта я вступил?

21

Решение

Значение protected является то, что производный тип будет иметь доступ к этому члену своя база а не какого-либо случайного объекта*. В вашем случае вы пытаетесь изменить bчлен, который находится вне вашего контроля (то есть вы можете установить this->a, но нет b.a)

Существует хак, чтобы заставить это работать, если вы заинтересованы, но лучшим решением будет рефакторинг кода, а не зависеть от взломов. Вы могли бы, например, предоставить конструктор в A это занимает A* в качестве аргумента (этот конструктор должен быть открытым), а затем инициализировать его в списке инициализатора B:

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

* protected предоставляет вам доступ к базовому члену в любом случае вашего собственного типа или производного от вашего собственного типа.

21

Другие решения

Здесь на самом деле есть две отдельные проблемы.

Во-первых, строка не просто выполняет присваивание, но пытается инициализировать базовый класс (который работает нормально) и член b, Чтобы создать b член должен построить его, и как член это нужно public доступ к конструктору, которого у него нет.

Тогда назначение также не может получить доступ к непубличному участнику b потому что, опять же, это не тип B но типа A вместо.

Помни что protected означает, что вы можете получить доступ к частям A через B только объект (или ребенок).

В этом случае сообщите нам свою реальную проблему, и мы постараемся помочь решить ее. Наследование и составление от одного типа — это дизайнерский запах.

2

Все компиляторы, которые я тестировал, жаловались на несколько вещей, и, в частности, защищенный конструктор был бы проблемой, даже если оператор присваивания был удален.

Вы не можете получить доступ к 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
// ...
}
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,

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector