[c++] Делегирование при переопределении оператора

danilov

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

class Base
{
public:
Base& operator<<(int value)
{
return *this;
}

virtual Base& operator<<(const char* v)
{
return *this;
}

};


#include "Base.h"

class Inherited: public Base
{

public:

Base& operator<<(const char* v)
{
Inherited& b = *this;
b << 10;
return *this;
}

};

Замена
Inherited& b = *this;
на
Base& b = *this;
работает.
VS2013

agent007new

Когда ты определяешь в наследемом класс метод, он скрывает (hides) такие же имена базоваго класс - компилятор просто перестает искать там метод. Победить можно или как ты сделал, или переопределив в наследуемом классе метод с нужной сигнатурой, или заиспользовать using и притащить из базового методы в текущую область видимости
 
class Base
{
public:
Base& operator<<(int value)
{
cout << "Base int" << endl;
return *this;
}

virtual Base& operator<<(const char* v)
{
cout << "Base char" << endl;
return *this;
}

};


class Inherited: public Base
{

public:
using Base::operator<<;

Base& operator<<(const char* v)
{
cout << "Derived char" << endl;
Inherited& b = *this;
b << 10;
return *this;
}

};


int main
{
Inherited i;
i << "zzz";
return 0;
}

Детали смотри здесь

danilov

Спасибо. Немного озадачивает, что объект ведёт себя по-разному, в зависимости от того, по ссылке какого типа он торчит.

PooH

еще можно такой изврат:
 
class Inherited : public Base
{

public:

Base& operator<<(const char* v)
{
Inherited& b = *this;
b.Base::operator<<(10);
return *this;
}

};

agent007new

Ну это как раз нормально, т.к. во время компиляции компилятору зачастую известен только статический тип указателя, а не реальный класс, на который он указывает, поэтому и компилирует в соответствие со статическим типом. Вот более очевидный пример, когда, надеюсь, очевидно, что логичное различающееся поведение
 
class Base
{
public:
void A {}
};


class Inherited: public Base
{
public:
void B {}
};


int main
{
Inherited* i = new Inherited;
i->B;

Base* b = i;
b->B; // Do not compile
return 0;
}

Мы не можем вызвать у b метод B, хотя для i можем, а это тот же самый объект.
По поводу сокрытия имен, почему это было сделано, есть пример здесь

agent007new

Ну да, про этот вариант я забыл

danilov

Здесь же ровно наоборот.
Я имел ввиду странно, что тривиальный каст (к базовому типу) меняет поведение. По идее наследник же во всех смыслах является объектом базового класса (ну, должен а оказывается нет.

agent007new

Ну да, этот вариант кажется нелогичным, конечно, но были причины, почему это сделается - я тебе ссылку указал, у саттера, вроде, было еще про это неплохо написано, но сходу, я что-то не нашел
Оставить комментарий
Имя или ник:
Комментарий: