Я получил неожиданный результат, который до сих пор не мог объяснить сам.
Хотя два раза объект одного и того же класса 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:
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";
}
Спасибо! Для меня окончательный вывод моего вопроса: если вы позвоните другу оператор<<(Станд :: ostream& ОС, постоянная база& объект) на объекте, в котором объект генерируется посредством динамической диспетчеризации. Вам нужно использовать виртуальные функции в вашем операторе<< чтобы обеспечить динамическую диспетчеризацию оператора<<,