Почему указатель this необходим для доступа к унаследованным атрибутам? - PullRequest
1 голос
/ 22 декабря 2010

предполагается, что задан следующий класс:

class Base{
public:

Base() {}
Base( const Base& b) : base_attr(b.base_attr) {}

void someBaseFunction()
{ .... }

protected:

SomeType base_attr;
};

Когда я хочу, чтобы класс унаследовал от него и включил новый атрибут для производного класса, я написал бы:

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->" в конструкторе копирования производного класса, компилятор жалуется, что "'base_attr'не было объявлено в этой области ".

Я думал, что при наследовании от класса защищенные атрибуты также будут доступны напрямую.Я не знал, что указатель "this->" нужен.Теперь я в замешательстве, если это действительно правильно, что я делаю там, особенно конструктор копирования класса Derived.

Поскольку каждый объект Derived должен иметь base_attr и производный_attr, и они, очевидно, должныбыть инициализирован / установлен правильно.А поскольку Derived наследуется от Base, я не хочу явно включать атрибут с именем «base_attr» в класс Derived.ИМХО, как правило, это разрушит идею наследования, поскольку все должно быть определено снова.


РЕДАКТИРОВАТЬ

Спасибо всем за быстрые ответы.Я полностью забыл тот факт, что классы на самом деле являются шаблонами.

Пожалуйста, ознакомьтесь с новыми примерами ниже, которые на самом деле компилируются при включении "this->" и завершаются ошибкой при пропуске "this->" в копии-строитель производного класса: базовый класс:

#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;
};

производный класс:

#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;
};

и для полноты также основная функция:

#include "derived.hpp"

int main()
{
        Derived<int> d; 
        d.printAttr();

        d.baseIncrement();
        d.printAttr();

        Derived<int> d2(d);
        d2.printAttr();

        return 0; 
};

Я использую g ++ - 4.3.4.Хотя теперь я понял, что это происходит из-за того, что я использую определения классов шаблонов, я не совсем понял, что вызывает проблему при использовании шаблонов и почему она работает, когда не используются шаблоны.Может ли кто-нибудь еще уточнить это?

Ответы [ 4 ]

3 голосов
/ 22 декабря 2010

Вы видите это, только если Base каким-то образом зависит от аргументов шаблона.

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

Поскольку это было смущающим, C ++ следует непротиворечивому правилу, согласно которому base_attr никогда не выполняется поиск в зависимом базовом классе при выполнении неквалифицированного поиска имени.Вам необходимо добавить префикс имени к this-> или к имени класса, как в Derived<T>::base_attr.Поэтому, когда базовый класс не объявляет base_attr, имя не указывает на потенциально глобально объявленное имя, а будет просто ошибкой во время компиляции.

3 голосов
/ 22 декабря 2010

Нет причин, чтобы это было необходимо. Все переменные-члены неявно доступны через this->, и я не знаю никаких языковых правил, которые бы указывали на необходимость использования this-> для доступа к любым функциям-членам или переменным.

1 голос
/ 22 декабря 2010

Я не знаю, почему вы получаете эту ошибку, не видя компилируемый пример, но вы можете написать свой конструктор копирования следующим образом:

Derived( const Derived& d ) : Base(d.base_attr), derived_attr(d.derived_attr) {}
0 голосов
/ 22 декабря 2010

Какой компилятор вы используете? Я не получаю никакой ошибки с g++ и не вижу ничего плохого в коде, который вы перечислили.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...