Возвращаемый тип не идентичен и не ковариантен возвращаемому типу «MediaDevice *» переопределенной виртуальной функции «MediaFactory :: FMediaDevice»

#c #factory #abstract

#c #фабрика #аннотация

Вопрос:

У меня есть следующая абстрактная фабрика:

 #include  "MediaDevice.h"

class MediaFactory {
public:
    MediaFactory();
    virtual ~MediaFactory();
    virtual  MediaDevice * FMediaDevice (int type) = 0;
};
  

и следующей фабрике, которая наследуется от абстрактной факторизации:

 #include "MediaFactory.h"
class JVCMedDevFactory : public MediaFactory {
public:
    MediaDevice* FMediaDevice (int type) {
        switch ((type_e)type) {
            case CDPlayer_e:
            return new JVCCdPlayer() ;
            case DVDPlayer_e:
                return new JVCVcrPlayer() ;
        }
} 
}; 
  

Мультимедийное устройство является :

 #include <string>
#include <utility>
using namespace std;
class MediaDevice {
 public:
MediaDevice();
    virtual ~MediaDevice();
virtual void Start () = 0 ;
virtual void Stop () = 0 ;
    virtual void Forward () = 0 ;
virtual void Rewind () = 0 ;
virtual pair <string,string> getName () const = 0;
protected:
pair <string,string> DeviceName;
};
  

Вот как я определяю проигрыватели JVC:

 #include "MediaDevice.h"
#include <iostream>
using namespace std;   
class JVCCdPlayer : public MediaDevice {
public:
    JVCCdPlayer(){
            DeviceName.first = "JVC";
            DeviceName.second = "CD";
    }
    void Start (){
    cout << "Playing " << this->getName().first << "," << this->getName().second <<     endl;
}
    void Stop (){
    cout << "Stopped " << this->getName().first << "," << this->getName().second     <<endl;
    }
    void Forward (){
    cout << "Rewind " << this->getName().first << "," << this->getName().second <<endl;
}
void     Rewind (){
    cout << "Forward " << this->getName().first << "," <<this->getName().second <<endl;
    }
    pair <string,string> getName () const{
    return DeviceName;
    }
    ~JVCCdPlayer(){}
   };
  

И я получаю следующую ошибку

Возвращаемый тип не идентичен и не ковариантен возвращаемому типу «MediaDevice *» переопределенной виртуальной функции «MediaFactory :: FMediaDevice»

Важно, что в visula studio у меня есть красная строка под FMediaDevice в объявлении MediaDevice* FMediaDevice (int type) { в классе MedDevFactory. И не имеет значения, что я возвращаю. Я могу вернуть 0 и все равно получить ошибку.

Почему?

Комментарии:

1. Нам нужно увидеть определения JVCCdPlayer и JVCVcrPlayer .

2. Ошибка, по-видимому, указывает на то, что MediaDevice выполняется преобразование в два разных типа между определением MediaFactory и JVCMedDevFactory . Используете ли вы прямые объявления в пространствах имен или что-то еще, что может привести к этому?

3. Я добавил объявления JVCCdPlayer и JVCVcrPlayer

4. @sera: Опубликуйте также содержимое "MediaDevice.h"

5. @Nawaz: Это уже есть. В разделе «Мультимедийное устройство — это:». Спасибо!

Ответ №1:

Из сообщения об ошибке кажется, что либо JVCCdPlayer либо JVCVcrPlayer (или оба) не являются производными от MediaDevice . Это так?

Вы должны получить оба из MediaDevice . Убедитесь, что ваши определения выглядят следующим образом:

 class JVCCdPlayer : public MediaDevice
{
};

class JVCVcrPlayer : public MediaDevice
{
};
  

Или где-то в иерархии, MediaDevice должен присутствовать.


Класс MediaDevice имеет данные-члены DeviceName , которые имеют тип pair<string,string> , но вы не включили заголовок, в котором pair определено. Поэтому включите <utility> . Аналогичным образом, убедитесь, что вы включили все необходимые заголовки.

Кроме того, я бы не стал писать using namespace std в заголовочном файле. Поэтому я бы переписал MediaDevice.h как :

 #ifndef MEDIA_DEVICE_H
#define MEDIA_DEVICE_H

#include <string>
#include <utility>

class MediaDevice 
{
  public:
     MediaDevice();
     virtual ~MediaDevice();
     virtual void Start () = 0 ;
     virtual void Stop () = 0 ;
     virtual void Forward () = 0 ;
     virtual void Rewind () = 0 ;
     virtual std::pair<std::string,std::string> getName () const = 0;
  private:
     std::pair<std::string,std::string> DeviceName;
};

#endif
  

То есть я бы квалифицировал каждое имя с помощью std:: вместо using namespace std .

Кстати, я не вижу определения следующей чисто виртуальной функции:

 virtual pair <string,string> getName () const = 0;
  

Вы определили это в производных классах? (хотя в ошибке не говорится, что это проблема, но все равно убедитесь и в этом).

Кроме того, данные участника DeviceName объявлены как, private что и должно быть protected , потому что вы обращаетесь к ним из производных классов JVCVcrPlayer и JVCCdPlayer .

Комментарии:

1. Из Visual Studio я вижу, что проблема связана с объявлением функции MediaDevice* FMediaDevice (тип int). Он помечает красной линией FMediaDevice. И для него не имеет значения, что я возвращаю. Я поставил retrun 0 и все равно увидел ошибку. Но JVCCDPlayer и JVCVcrPlayer также получены из MediaDevice. Что это значит «MediaDevice должно присутствовать.» ? Большое спасибо!

2. @sera: почему pair не требует заголовка? Кроме того, я предполагаю, что ваша программа выдает другую ошибку. Вы опубликовали все сообщения об ошибках?

3. @Nawaz: Я предполагаю, что уже включенные заголовки неявно включают <utility> в Visual Studio.

4. @Nawaz : Прошу прощения. Я проверил сейчас и действительно увидел другую ошибку: она помечена красной строкой под — return new JVCCdPlayer(); — и сказал, что объект типа абстрактного класса JVCCdPlayer не разрешен. Я полагаю, это произошло потому, что я изменил сегодня классы JvcCdPlayer и JVCVcrPlayer и удалил из них реализацию чисто виртуальных функций. Но все равно, даже если я не использую эти классы. Вместо этого возвращайте только 0. Первая ошибка, о которой я упомянул, все еще существует. Я использовал только #include <string>, используя std пространства имен; заголовки для пары

5. @sera: ДА. Я был прав. Это потому, что вы не определили getName чисто виртуальную функцию в производных классах. Всегда помните, что чисто виртуальные функции должны быть реализованы в производных классах!

Ответ №2:

MediaDevice, вероятно, не является родительским для JVCCdPlayer или JVCVcrPlayer.

Также обратите внимание, что функция JVCMedDevFactory::FMediaDevice не всегда гарантированно возвращает значение — у вас должен быть регистр по умолчанию в инструкции switch или возврат по умолчанию в нижней части функции.

Комментарии:

1. Большое спасибо вам за помощь, Как я уже сказал, я попытался оставить только одну строку — return 0 в реализации функции JVCMedDevFactory::FMediaDevice и все равно остался с ошибкой

Ответ №3:

После следующих изменений Visual Studio 2010 скомпилировала ваш код (хотя я поместил все это в один исходный файл).

  1. Включая все требуемые заголовки;
  2. Создание MediaDevice::DeviceName защищенного (не закрытого) члена, чтобы к нему могли обращаться конструкторы игровых классов;
  3. Определение type_e как перечисление;
  4. Удаление =0 спецификатора «pure virtual» из объявлений MediaDevice функций-членов и добавление очевидного определения для `MediaDevice::getName().

В реальном коде на последнем шаге вместо этого следовало бы добавить переопределяющие определения чисто виртуальных функций в классы проигрывателя, но мне было лень писать это.

Я должен сказать, что ни на одном этапе я не видел диагностики «Возвращаемый тип не идентичен и не ковариантен с».

Надеюсь, это поможет.

Комментарии:

1. Я полагаю, у меня проблема с «включением всех необходимых заголовков». Можете ли вы показать, как вы размещаете заголовки? Спасибо

2. @sera: Мне нужно было добавить #include <iostream> для std::cout , и я также добавил #include <utility> для std::pair , хотя это неявно включено через какой-то другой заголовок VC.

3. Спасибо за помощь. Я следовал инструкциям Nawaz, и это решило проблему. Но я считаю, что ваше решение также было хорошим.