наследование — ковариантность C ++ неожиданное поведение

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

Хотя два раза объект одного и того же класса BASIC2 (наследование от BASIC1) генерируется другое сообщение при использовании друга operator<< на сгенерированный объект.

Смотрите код ниже

Я позволяю D (объект класса Derived который наследует от Base) создать объект класса BASIC2 и назови его другом operator<<, Это производит ожидаемое сообщение "BASIC2 object",

Я позволяю B генерировать объект класса BASIC1 и позвони своему другу operator<<, Это выводы "BASIC1 object" как я и предполагал.

Затем я использую виртуальное наследование, чтобы B2 (Base* B2 = &D;) создать объект BASIC2, Я следую за потоком кода в отладчике (Visual Studio 2010), и это правильно генерирует объект BASIC2, Тем не менее, друг operator<< не вызывается на BASIC2 объект, но использует друг operator<< из класса BASIC1 (и, следовательно, выходы "BASIC1 object").

Обратите внимание, я тоже хочу BASIC2 наследовать от BASIC1 как я хочу использовать ковариационное поведение.

int main(int argc, char* argv[]) {
Base B;
Derived D;
Base* B2 = &D;
std::cout << *D.generate(0) << std::endl;
std::cout << *B.generate(0) << std::endl;
std::cout << *(B2->generate(0)) << std::endl;
system("pause");
}

Выход:

BASIC2 объект
BASIC1 объект
BASIC1 объект
class BASIC1 {
public:
friend std::ostream& operator<<(std::ostream& os, const BASIC1& basic) {
os << "BASIC1 object";
return os;
}
};

class BASIC2 : public BASIC1 {
friend std::ostream& operator<<(std::ostream& os, const BASIC2& basic) {
os << "BASIC2 object";
return os;
}
};

class Base {
public:
virtual BASIC1* generate(double num) const {
return new BASIC1();
}
protected:
private:
};

class Derived : public Base {
public:
virtual BASIC2* generate(double num) const override {
return new BASIC2();
}
protected:
private:
};

1

Решение

Выбор оператора<< основан на статическом типе вашего объекта, известного во время компиляции. Чтобы добиться того, что вы хотите, не определяйте два оператора<< функция, но одна только в бейсике1:

    friend std::ostream& operator<<(std::ostream& os, const BASIC1& basic) {
Write(os);
return os;
}

и определите виртуальную функцию Write в BASIC1 и BASIC2, чтобы сделать то, что вы хотите:

virtual void Write(std::ostream& os) const {
os << "BASIC1 object";
}
5

Другие решения

Спасибо! Для меня окончательный вывод моего вопроса: если вы позвоните другу оператор<<(Станд :: ostream& ОС, постоянная база& объект) на объекте, в котором объект генерируется посредством динамической диспетчеризации. Вам нужно использовать виртуальные функции в вашем операторе<< чтобы обеспечить динамическую диспетчеризацию оператора<<,

1

По вопросам рекламы [email protected]