C++: Why does my DerivedClass's constructor not have access to the BaseClass's protected field?

25,788

Solution 1

You cannot initialize m_data in the derived class constructor but instead pass it as an argument to the base class constructor.

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

Solution 2

In the initializer list you can just set values for attributes of the same class. To access it, you must attribute the value in the body of the constructor:

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

Or, if it is expensive to copy the object, you pass the m_data as an argument to the parent class constructor :

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

Tip: Pass your data as a reference to prevent the copy constructor.

See more info here: order of initialization of C++ constructors.

Solution 3

You are not "accessing" m_data -- you are initializing it. However, it's already been initialized in the Base Class's ctor. If you want to change it's value, assign to it in the body of your ctor:

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

Solution 4

You need to call the base class constructor as follows:

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

Each class should be in charge of initializing it's members.

Solution 5

Initializer lists can only be used to initialize fields which are owned by the type in question. It is not legal to initialize base class fields in an initializer lists which is why you receive this error. The field is otherwise accessible within DerivedClass

Share:
25,788
dwinchell
Author by

dwinchell

Updated on July 09, 2020

Comments

  • dwinchell
    dwinchell almost 4 years

    I have a constructor attempting to initialize a field in a base class. The compiler complains. The field is protected, so derived classes should have access.

    //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() { }
    

    //The compiler error

    DerivedClass.cpp:3: error: class ‘DerivedClass’ does not have any field named ‘m_data’

    Any help is greatly appreciated. Thank you in advance.

  • J3STER
    J3STER over 7 years
    you have no idea how helpfull this was
  • underscore_d
    underscore_d almost 6 years
    Assigning members in the body of the constructor should be discouraged, so I would consign that to a footnote at most. Also, nowadays that string should be std::move()d into the member or base class in order to avoid a pointless copy.
  • underscore_d
    underscore_d almost 6 years
    Sure, they can do that, but they probably shouldn't and don't really want to! Assigning members in the body of the constructor should be discouraged, and I think that should be especially emphasised if it's a base class's member! This will waste resources assigning a value that gets changed shortly after, introduce an intermediate state that gets discarded between the init-list of the base and the constructor body of the derived class, etc. It's just best avoided.