C ++: Почему конструктор моего DerivedClass не имеет доступа к защищенному полю BaseClass? - PullRequest
27 голосов
/ 23 июля 2010

У меня есть конструктор, пытающийся инициализировать поле в базовом классе. Компилятор жалуется. Поле защищено, поэтому производные классы должны иметь доступ.

//The base class: 

class BaseClass

{

public:

    BaseClass(std::string);
    BaseClass(const BaseClass& orig);
    virtual ~BaseClass();
    const std::string GetData() const;
    void SetData(const std::string& data);
protected:

    BaseClass();
    std::string m_data;

};

BaseClass::BaseClass(const std::string data) : m_data(data) { }

BaseClass::BaseClass() { } 

BaseClass::BaseClass(const BaseClass& orig) { }

BaseClass::~BaseClass() { }

void BaseClass::SetData(const std::string& data)
{
    m_data = data;
}

const std::string BaseClass::GetData() const
{
    return m_data;
}


//The derived class: 


class DerivedClass : public BaseClass
{

public:

    DerivedClass(std::string data);
    DerivedClass(const DerivedClass& orig);
    virtual ~DerivedClass();
private:

};

DerivedClass::DerivedClass(std::string data) : m_data(data) { } //ERROR HERE

DerivedClass::DerivedClass(const DerivedClass& orig) { }

DerivedClass::~DerivedClass() { }

// Ошибка компилятора

DerivedClass.cpp: 3: ошибка: класс «DerivedClass» не имеет поля с именем «m_data»

Любая помощь очень ценится. Заранее спасибо.

Ответы [ 6 ]

46 голосов
/ 23 июля 2010

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

То есть: DerivedClass::DerivedClass(std::string data) : BaseClass(data) { }

7 голосов
/ 23 июля 2010

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

DerivedClass :: DerivedClass (std :: string data) {m_data = data;}

Или, если копировать объект дорого, вы передаете m_data в качестве аргумента конструктору родительского класса:

DerivedClass :: DerivedClass (std:: string data): BaseClass (data) {}

Совет. Передайте данные в качестве ссылки для предотвращения конструктора копирования.

См. дополнительную информацию здесь: порядокинициализация конструкторов C ++ .

4 голосов
/ 23 июля 2010

Вы не «обращаетесь» к m_data - вы его инициализируете. Тем не менее, он уже был инициализирован в ctor базового класса. Если вы хотите изменить его значение, присвойте ему в теле вашего ctor:

DerivedClass::DerivedClass(std::string data) 
{
   m_data = data;
}
2 голосов
/ 23 июля 2010

Вам нужно вызвать конструктор базового класса следующим образом:

DerivedClass::DerivedClass(std::string data) : BaseClass(data) {
}

Каждый класс должен отвечать за инициализацию своих членов.

1 голос
/ 23 июля 2010

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

0 голосов
/ 23 июля 2010

Ваш конструктор производного класса действительно имеет доступ, но вы не можете назначить его в списке инициализации. Измените конструктор на:

<code>DerivedClass::DerivedClass(const std::string& data)
 : BaseClass(data)
{
}

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

<code>DerivedClass::DerivedClass(const std::string& data)
{
    m_data = data;
}
...