开发者

Why is the this-pointer needed to access inherited attributes?

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 n开发者_如何学Cew 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 Base in some way depends on template arguments.

In that case, it's deemed too dangerous that a name like base_attr is 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_attr is never lookup in a dependent base class when doing unqualified name lookup. You need to prefix the name with this-> or with the name of the class as in Derived<T>::base_attr. So when the base class doesn't declare a base_attr, the name doesn't silently refer to a potentially globally declared name, but it will just be a compile time error.


There is no reason that this should be necessary. All member variables are implicitly accessed through this-> and I know of no language rules that specify that you should need to use this-> to access any member functions or variables.


I don't know why you're getting that error without seeing a compilable example, but you can write your copy constructor thus:

Derived( const Derived& d ) : Base(d.base_attr), derived_attr(d.derived_attr) {}


What compiler are you using? I'm not getting any error with g++ and nor do I see anything wrong with the code you have listed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜