Полимофизм для оператора "<<"
#include <iostream>
class A {};
class B : public A {};
std::ostream& operator<<(std::ostream& out, const A* a) {
return out << "A";
}
std::ostream& operator<<(std::ostream& out, const B* B) {
return out << "B";
}
int main() {
A* arr[2];
arr[0] = new A();
arr[1] = new B();
std::cout << arr[0] << arr[1];
}
Вот пример программы, которая выводит AA, как мне уточнить без явного каста к B(типо B*(arr[1])), что оператор << должен принимать B во втором случае?
Ответы (2 шт):
А зачем? Может, лучше пусть ваш оператор << для A использует внутри виртуальную функцию? Тем более что в вашем варианте ничего виртуального нет, и в результате нет и полиморфизма.
Вот такое решение вас не устроит?
class A {
public:
virtual string name() const { return "A"; }
};
class B : public A {
public:
string name() const override { return "B"; }
};
std::ostream& operator<<(std::ostream& out, const A& a) {
return out << a.name();
}
int main() {
A* arr[2];
arr[0] = new A();
arr[1] = new B();
std::cout << *arr[0] << *arr[1];
}
Чтобы говорить о каком-то полиморфизме - нужны виртуальные функции. В вашем примере их вовсе нет. А есть всего лишь две перегруженные функции operator<<, отличающиеся типом последнего параметра. Какая из перегруженных функций будет вызвана определяется статическими типами переменных, передаваемых в функцию. Что arr[0], что arr[1] имеют статический тип A*, а значит будет вызвана первая перегрузка в обоих случаях.
std::cout << arr[0] << arr[1];
// Т.е. вот здесь ^^ нет ничего такого, что сказало бы компилятору - бери динамический тип!
Кстати, замечу, что при перегрузке операторов обычно используются ссылки, а не указатели. Собственно, ссылки в языке и появились, чтобы можно было красиво сделать перегрузку операторов.
Другой момент в том, что operator<< по смыслу первым аргументом должен принимать поток вывода, а для виртуальных функций первым аргументом всегда будет объект this, для которого реализуется эта виртуальная диспетчеризация. Ну а вообще, можно вот так извратиться (не делайте так!):
#include <iostream>
struct A {
virtual std::ostream& operator<< (std::ostream& o) { o << "A"; return o; }
};
struct B : A {
std::ostream& operator<< (std::ostream& o) override { o << "B"; return o; }
};
int main()
{
A* arr[2] = {new A, new B};
*arr[0] << std::cout;
*arr[1] << std::cout;
}
Вывод:
AB
P.S. Адекватная реализация вашей задачи уже представлена в ответе Harry.