Подтвердить что ты не робот

С++: Почему у моего конструктора DerivedClass нет доступа к полю, защищенному BaseClass?

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

//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​​p >

Любая помощь приветствуется. Заранее благодарю вас.

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

DerivedClass:: DerivedClass (std::string data): BaseClass (данные) {}

Совет. Передайте свои данные в качестве ссылки, чтобы предотвратить создание конструктора копии.

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

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

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

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