2010-02-18 2 views
111

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

Некоторые примеры кода:

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

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

Когда я пытаюсь это, компилятор говорит мне: «класс„ребенок“не имеет никакого поля с именем" что-то». Что-то вроде этого возможно? Если да, то какой синтаксис?

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

ответ

103

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

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

    std::string something; 
} 

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

Это точно обходной путь я уже придумал. По крайней мере, теперь мне не нужно беспокоиться о том, можно ли это сделать. :) – Stephen

11

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

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

51

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

От C++ 0x проект:

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

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

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

+2

Спасибо, что указал мне на «почему». Делает полный смысл. Я слишком долго не был в C++ ... :) – Stephen

0

Может быть, вы можете попробовать его таким образом с помощью ключевого слова «с помощью»

class Parent 
{ 

protected: 
std::string something; 
}; 

class Child : public Parent 
{ 

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