assume the following class is given:
class Base{
public:
Base() {}
Base( const Base& b) : base_attr(b.base_attr) {}
void someBaseFunction()
{ .... }
protected:
SomeType base_attr;
};
When I want a class to inherit from this one and include a new attribute for the derived class, I would write:
class Derived: public Base {
public:
Derived() {}
Derived( const Derived& d ) : derived_attr(d.derived_attr)
{
this->base_attr = d.base_attr;
}
void SomeDerivedFunction()
{ .... }
private:
SomeOtherType derived_attr;
};
This works for me (let’s ignore eventually missing semicolons or such please).
However, when I remove the “this->” in the copy constructor of the derived class, the compiler complains that “‘base_attr’ was not declared in this scope”.
I thought that, when inheriting from a class, the protected attributes would then also be accessible directly. I did not know that the “this->” pointer was needed.
I am now confused if it is actually correct what I am doing there, especially the copy-constructor of the Derived-class.
Because each Derived object is supposed to have a base_attr and a derived_attr and they obviously need to be initialized/set correctly.
And because Derived is inheriting from Base, I don’t want to explicitly include an attribute named “base_attr” in the Derived-class. IMHO doing so would generally destroy the idea behind inheritance, as everything would have to be defined again.
EDIT
Thank you all for the quick answers. I completely forgot the fact that the classes actually are templates.
Please, see the new examples below, which are actually compiling when including “this->” and are failing when omiting “this->” in the copy-constructor of the Derived-class:
Base-class:
#include <iostream>
template<class T>
class Base{
public:
Base() : base_attr(0) {}
Base( const Base& b) : base_attr(b.base_attr) {}
void baseIncrement()
{ ++base_attr; }
void printAttr()
{
std::cout << "Base Attribute: " << base_attr << std::endl;
}
protected:
T base_attr;
};
Derived-class:
#include "base.hpp"
template< class T >
class Derived: public Base<T>{
public:
Derived() : derived_attr(1) {}
Derived( const Derived& d) : derived_attr(d.derived_attr) {
this->base_attr = d.base_attr;
}
void derivedIncrement()
{ ++derived_attr; }
protected:
T derived_attr;
};
and for completeness also the main function:
#include "derived.hpp"
int main()
{
Derived<int> d;
d.printAttr();
d.baseIncrement();
d.printAttr();
Derived<int> d2(d);
d2.printAttr();
return 0;
};
I am using g++-4.3.4.
Although I understood now that it seems to come from the fact that I use template-class definitions, I did not quite understand what is causing the problem when using templates and why it works when not using templates. Could someone please further clarify this?
You are only seeing this if
Basein some way depends on template arguments.In that case, it’s deemed too dangerous that a name like
base_attris lookup up in such a dependent base class: For some template instantiation, the name could be found in the base class, and for another instantiation, the member could be absent and the name would refer to a some namespace member.Because this was thought to be confusing, C++ follows the consistent rule that
base_attris never lookup in a dependent base class when doing unqualified name lookup. You need to prefix the name withthis->or with the name of the class as inDerived<T>::base_attr. So when the base class doesn’t declare abase_attr, the name doesn’t silently refer to a potentially globally declared name, but it will just be a compile time error.