Функция Get не будет работать на виртуальном методе - PullRequest
0 голосов
/ 06 апреля 2019

извините, если это глупый вопрос, но я стараюсь изо всех сил учить cpp ..

Итак, я тренировался с классами, и я сомневался в этом коде, здесь позвольте мне показать вам

class C {
     private:
         //pv
     protected:
         //pt
     public:
         //constructors etc.

         virtual ostream& print(ostream&, const C&) const;
};

Class D: public C {
      private:
         int b;
      public:
         //constructors etc.
         int get_b() const {return b;}

         virtual ostream& print(ostream&, const C&) const;
};

Итак, давайте предположим, что я хочу напечатать переменные-члены моего класса, я мог (должен?) Использовать функции get, верно?Но моя проблема в том, что когда я вызываю виртуальную функцию и пытаюсь распечатать переменные-члены

//in cpp

ostream& operator<<(ostream& os, const D& d) {

    d.print(os);
    return os;
}
ostream& D::print(ostream& os, const C& c) const {

    os<<(C&)c;
    os<<c.get_b();
    return os;
}

Вот проблема, она говорит [Error] 'const class C' has no member named 'get_a', и это абсолютно верно, но тогда как я могу использовать виртуальнуюфункция, которая нуждается в получении / множестве других классов в иерархии?По определению D должен был унаследовать каждый открытый метод, кроме некоторых, что означает, что функции get / set должны быть также функциями D, верно?Извините, если я был слишком долго!

Ответы [ 3 ]

0 голосов
/ 06 апреля 2019

Я предлагаю следующую стратегию.

  1. Используйте функцию-член virtual, чтобы объекты типа C (и его производные типы) могли записывать данные, специфичные для типа, в std::ostream.

    virtual std::ostream& write(std::ostream& out) const;
    
  2. Используйте функцию, не являющуюся членом, чтобы позволить вам использовать любой производный объект базового класса с помощью оператора <<. Это можно реализовать с помощью функции-члена virtual.

    std::ostream& operator<<(std::ostream& out, C const& c)
    {
       return c.write(out);
    }
    

Пример реализации функций-членов virtual:

class C {

   public:

      virtual std::ostream& write(ostream& out) const
      {
         // Write data specific to this class
         // ...

         return out;
      }
};

class D: public C {

   private:

      int b;

   public:

      virtual std::ostream& write(ostream& out) const
      {
         // Call the base class to do its job first.
         C::write(out);

         // Write data specific to this class
         out << b;

         return out;
      }
};

Эта стратегия гарантирует, что все данные, которые находятся на определенном уровне в иерархии наследования классов, обрабатываются только на этом уровне. Базовые классы не должны знать, что производные классы делают, а производные классы не беспокоятся о том, как это делают базовые классы.

Теперь вы можете использовать:

D d{...};
std::cout << d << std::endl;
0 голосов
/ 06 апреля 2019

В вашем коде есть несколько проблем.Во-первых, некоторые из ваших функций const, а не другие.Если предполагается, что они являются «одной и той же» виртуальной функцией, то они должны совпадать.

Тогда очевидный вопрос: почему вы хотите передать C сверху?У вас уже есть this:

virtual ostream& operator<<(ostream& os, const C& c) const {
    c.print(os);
    return os;
}

ostream& D::print(ostream& os) const override {
    os<<this->get_b();
    return os;
}

Если у вас есть экземпляр C или производная версия, это будет работать, поскольку D является C и будет вызываться переопределенное значение print.

0 голосов
/ 06 апреля 2019

Вы не можете вызвать c.get_b (), если c - это C, потому что в C такой функции нет, а C также не является производным от класса, в котором определен get_b ().

Я бы сделал фиктивную функцию get_b () в классе C.

PS: Полагаю, вы имели в виду get_b вместо get_a.

...