Почему приведение к базовому классу в виртуальной функции дает ошибку сегментации? - PullRequest
2 голосов
/ 17 апреля 2010

Я хочу распечатать производный класс, используя operator<<. Когда я печатаю производный класс, я хочу сначала напечатать его базу, а затем собственный контент.

Но я столкнулся с некоторой проблемой (см. Segfault ниже):

class Base {
 public:
  friend std::ostream& operator<<(std::ostream&, const Base&);
  virtual void Print(std::ostream& out) const {
    out << "BASE!";
  }
};
std::ostream& operator<<(std::ostream& out, const Base& b) {
  b.Print(out);
  return out;
}

class Derived : public Base {
 public:
  virtual void Print(std::ostream& out) const {
    out << "My base: ";
    //((const Base*)this)->Print(out); // infinite, calls this fct recursively
    //((Base*)this)->Print(out);       // segfault (from infinite loop?)                                                          
    ((Base)*this).Print(out);          // OK
    out << " ... and myself.";
  }
};

int main(int argc, char** argv){
    Derived d;
    std::cout << d;
    return 0;
}

Почему я не могу разыграть один из этих способов?

    ((const Base*)this)->Print(out); // infinite, calls this fct recursively
    ((Base*)this)->Print(out);       // segfault (from infinite loop?)

Ответы [ 4 ]

6 голосов
/ 17 апреля 2010

Try Base :: Print (out)

4 голосов
/ 17 апреля 2010

К вопросу почему :

  1. ((Base)*this).Print(out); слайсы текущий экземпляр к Base типу временного. Это приводит к прямому вызову метода базового класса.
  2. ((const Base*)this)->Print(out); вызывает виртуальный метод через указатель на базу, которая преобразуется в метод дочернего класса, что приводит к бесконечной рекурсии.
  3. ((Base*)this)->Print(out); - Я почти уверен, что это неопределенное поведение.
2 голосов
/ 17 апреля 2010

используйте Base::Print вместо. Виртуальные функции переопределяются производным классом. По сути, вы называете печать снова и снова

0 голосов
/ 06 февраля 2015

Предлагаю прочитать C ++ Primer, 5-я страница 607 «Обход виртуального механизма», который представляет собой короткий раздел, рассказывающий о том, какую ошибку бесконечной рекурсии вы сделали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...