Настройка поддержки cout в структурах с несколькими уровнями наследования - PullRequest
1 голос
/ 06 марта 2012
#include <iostream>
#include <string>

struct Printable abstract
{
 friend std::ostream& operator<<(std::ostream& cout, const Printable& obj)
 {
  obj.print(cout);

  return cout;
 }

 virtual void print(std::ostream& cout) const = 0;
};

struct VirtualBase abstract : public Printable
{
 //stuff
};

struct Named abstract : public Printable
{
 std::string name;

 void print(std::ostream& cout) const
 {
  cout << "Name: " << name;
 }
};

struct DerivedA : public VirtualBase
{
 void print(std::ostream& cout) const
 {
  cout << "DerivedA";
 }
};

struct DerivedB : public VirtualBase, public Named
{
 void print(std::ostream& cout) const
 {
  cout << "DerivedB";

  dynamic_cast<const Named*>(this)->print(cout);
  //Is there a better way to call Named::print?
 }
};

Поскольку DerivedB наследует VirtualBase и Named, и оба они наследуют Printable, я не могу использовать DerivedB с cout. Каков наилучший способ обеспечить поддержку печати на нескольких уровнях иерархии наследования? Кроме того, что было бы самым простым способом вызвать Named :: print в печати производного класса?

Ответы [ 3 ]

1 голос
/ 06 марта 2012

Проблема в том, что DerivedB - это VirtualBase (что является Printable) и Named (что является Printable), поэтому operator<< пытается преобразовать DerivedB в Printable, но не может быть понижен, потому что это два Printable объекта, и он не знает, к какому из них понижать. Поскольку вы хотите, чтобы DerivedB производился только от одного Printable объекта, вы должны использовать виртуальное наследование .

   normal inheritance:            virtual inheritance:
Printable      Printable                 Printable
   |               |                    /        \
VirtualBase      Named          VirtualBase      Named
       \         /                     \         /
        DerivedB                         DerivedB

Что делается просто:

struct Named abstract : virtual public Printable
struct VirtualBase abstract : virtual public Printable

Обратите внимание, что класс с виртуальным наследованием больше и на немного * на 1025 * медленнее, чем без него, но, с другой стороны, C ++ является одним из очень немногих языков , который может это делать вообще .

0 голосов
/ 06 марта 2012

Хорошо, я нашел способ исправить это путем шаблонной перегрузки оператора:

 template<typename P> friend std::ostream& operator<<(std::ostream& cout, const P& obj)
 {
  obj.print(cout);

  return cout;
 }

Я не уверен, насколько это стабильно.

0 голосов
/ 06 марта 2012

Вам просто нужно указать, какой print вы хотите вызвать с помощью оператора разрешения области (::), например:

Named::print(cout);
...