Инициализировать родительские защищенные элементы с помощью списка инициализации (С++)

Можно ли использовать список инициализации конструктора дочернего класса для инициализации элементов данных, объявленных как защищенные в родительском классе? Я не могу заставить его работать. Я могу обойти это, но было бы неплохо, если бы мне не пришлось.

Пример кода:

class Parent
{
protected:
    std::string something;
};

class Child : public Parent
{
private:
    Child() : something("Hello, World!")
    {
    }
};

Когда я пытаюсь это сделать, компилятор говорит мне: "У класса" Child "нет поля с именем" something ". Что-то вроде этого возможно? Если да, то какой синтаксис?

Большое спасибо!

Ответ 1

Это невозможно в том, как вы описываете. Вам нужно будет добавить конструктор (может быть защищен) базовому классу для его пересылки. Что-то вроде:

class Parent
{
protected:
    Parent( const std::string& something ) : something( something )
    {}

    std::string something;
}

class Child : public Parent
{
private:
    Child() : Parent("Hello, World!")
    {
    }
}

Ответ 2

Когда компилятор попадает в список инициализаторов, объект производного класса еще не сформирован. Конструктор базового класса до этого не был вызван. Только после того, как был вызван конструктор базового класса, появляется something. Отсюда и проблема. Когда вы не вызываете конструктор базового класса явно, компилятор делает это для вас (путем создания соответствующего тривиального конструктора для базового класса). Это приводит к инициализации элемента something.

Из С++ 0x черновик:

12.6.2 Инициализация баз и членов

2 Имена в mem-initializer-id поднял вопрос о класс конструкторов и, если не найден в этой области, рассматриваются в область, содержащая конструкторы определение. [Примечание: если класс конструкторов содержит член с тем же именем, что и прямой или виртуальный базовый класс класса, mem-initializer-id, обозначающий участника или базовый класс и состоящий из одного идентификатор относится к члену класса. Идентификатор meminitializer для скрытого базовый класс может быть указан с использованием квалифицированное имя. -end note] Если mem-initializer-id называет класс конструкторов, нестатические данные член класса конструкторов или прямой или виртуальной базой этого класса, mem-инициализатор плохо сформирован.

Примечание: Акцент мой.

Ответ 3

Вы не можете инициализировать элементы родительского класса в списке инициализации конструктора производного класса. Неважно, защищены ли они, публично или что-то еще.

В вашем примере член something является членом класса Parent, что означает, что его можно инициализировать только в списке инициализатора конструктора класса Parent.

Ответ 4

Возможно, вы можете попробовать его таким образом, используя ключевое слово "using"

class Parent
{

protected:
std::string something;
};

class Child : public Parent
{

private:
using Parent::something;
Child()
{
    something="Hello, World!";
}
};