Тип возврата не идентичен и не ковариантен с типом возврата MediaDevice * переопределенной виртуальной функции MediaFactory :: FMediaDevice

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

#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 и все равно получить ошибку.

Почему?


person serpentina    schedule 28.05.2011    source источник
comment
Нам нужно увидеть определения JVCCdPlayer и JVCVcrPlayer.   -  person Xeo    schedule 29.05.2011
comment
Ошибка, кажется, указывает на то, что MediaDevice разрешается к двум различным типам между определениями MediaFactory и JVCMedDevFactory. Используете ли вы форвардные объявления в пространствах имен или что-то, что может вызвать это?   -  person CB Bailey    schedule 29.05.2011
comment
Я добавил объявления JVCCdPlayer и JVCVcrPlayer   -  person serpentina    schedule 29.05.2011
comment
@sera: Разместите также содержание "MediaDevice.h"   -  person Nawaz    schedule 29.05.2011
comment
@Nawaz: Это уже есть. В разделе «Медиа-устройство» находится :. Спасибо!   -  person serpentina    schedule 29.05.2011
comment
@sera: см. правку в моем сообщении.   -  person Nawaz    schedule 29.05.2011
comment
Голосование за закрытие, так как проблема была решена в автономном режиме, информация доступна не всем зрителям.   -  person CB Bailey    schedule 29.05.2011


Ответы (3)


Из сообщения об ошибке видно, что либо 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.

person Nawaz    schedule 28.05.2011
comment
Из визуальной студии я вижу, что проблема связана с объявлением функции MediaDevice * FMediaDevice (тип int). Он помечается красной линией FMediaDevice. И ему все равно, что я верну. Я поставил retrun 0 и все равно увидел ошибку. Но JVCCDPlayer и JVCVcrPlayer также являются производными от MediaDevice. Что это означает, что должен присутствовать MediaDevice. ? Большое спасибо! - person serpentina; 29.05.2011
comment
@sera: почему pair не требует заголовка? Кроме того, я предполагаю, что ваша программа выдает другую ошибку. Вы публиковали все сообщения об ошибках? - person Nawaz; 29.05.2011
comment
@Nawaz: я думаю, что уже включенные заголовки неявно включают <utility> в Visual Studio. - person Alexey Kukanov; 29.05.2011
comment
@Nawaz: Мне очень жаль. Я проверил сейчас и действительно увидел еще одну ошибку: она отмечена красной линией под - return new JVCCdPlayer (); - и сказал, что объект абстрактного класса типа JVCCdPlayer не допускается. Полагаю, это произошло потому, что я сегодня изменил классы JvcCdPlayer и JVCVcrPlayer и удалил из них реализацию чистых виртуальных функций. Но даже если я не использую эти классы. Вместо этого верните только 0. Первая ошибка, о которой я упомянул, все еще существует. Я использовал только #include ‹string›, используя пространство имен std; заголовки для пары - person serpentina; 29.05.2011
comment
@sera: ДА. Я был прав. Это потому, что вы не определили getName чистую виртуальную функцию в производных классах. Всегда помните, что чистые виртуальные функции должны быть реализованы в производных классах! - person Nawaz; 29.05.2011
comment
@Nawaz: Я вернул реализацию чистых виртуальных функций классу JVCCdPlayer. Это устранило новую ошибку. Но я все равно получаю первую ошибку. : - ((((( - person serpentina; 29.05.2011
comment
@sera: Я тебя не понял. Можете ли вы прислать мне свой код, чтобы я сам увидел все файлы и определения и рассказал вам о проблеме? - person Nawaz; 29.05.2011
comment
@Nawaz: где я могу получить электронную почту? Спасибо! - person serpentina; 29.05.2011
comment
@Nawaz: Спасибо. Я отправил проект на вашу электронную почту. - person serpentina; 29.05.2011
comment
@sera: хорошо, поняла. теперь позвольте мне увидеть, что с этим не так. отвечу, как только найду проблему. - person Nawaz; 29.05.2011
comment
@sera: ты где? вам следует зайти в онлайн на Gmail. - person Nawaz; 29.05.2011
comment
@Nawaz, @sera: Хотя этот ответ отмечен как принятый, я все еще не могу понять, как была решена неидентичная и нековариантная ошибка. В чем была настоящая проблема? - person CB Bailey; 29.05.2011
comment
@Charles: На самом деле было слишком много проблем, поэтому я попросил его прислать мне код, я решил это в автономном режиме. Здесь он не смог воспроизвести ошибку. - person Nawaz; 29.05.2011
comment
@Nawaz: Мне все еще любопытна основная проблема. У меня была пара подозрений. В любом случае этот вопрос следует закрыть, поскольку на него явно нельзя ответить на основании опубликованной информации. - person CB Bailey; 29.05.2011
comment
@ Чарльз: Много проблем: 1) он не определил main(); 2) в заголовках не было охранников, из-за которых были ошибки переопределения; 3) он не определил конструктор и деструктор в интерфейсе; 4) он объявил DeviceName в частном разделе, но получал доступ к нему из производных классов. Такие вещи - person Nawaz; 29.05.2011

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

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

person Vinnyq12    schedule 28.05.2011
comment
Большое спасибо за вашу помощь, как я уже сказал, я попытался оставить только одну строку - вернуть 0 в реализации функции JVCMedDevFactory :: FMediaDevice и все равно остался с ошибкой - person serpentina; 29.05.2011

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

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

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

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

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

person Alexey Kukanov    schedule 29.05.2011
comment
Полагаю, у меня проблема с включением всех необходимых заголовков. Можете показать, как вы ставите заголовки? Спасибо - person serpentina; 29.05.2011
comment
@sera: Мне нужно было добавить #include <iostream> для std::cout, и я также добавил #include <utility> для std::pair, хотя он неявно включен через какой-то другой заголовок VC. - person Alexey Kukanov; 29.05.2011
comment
Спасибо за помощь. Я выполнил инструкции Nawaz, и проблема была решена. Но я считаю, что ваше решение тоже было хорошим. - person serpentina; 29.05.2011