2013-07-12 5 views
0

Я пытаюсь создать очень модульную программу с использованием интерфейсов. Исходя из фона C#, я бы использовал интерфейсы как типы переменных, поэтому я мог использовать полиморфизм, позволяя мне/другим передавать много разных объектов, которые наследуют этот интерфейс в функцию/переменную. Однако при попытке сделать это на C++ я получаю много странных ошибок. Что я здесь делаю неправильно?Объявление и определение интерфейса C++

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

ILogger * errorLogger = ErrorLogger(); 

error C2440: 'initializing' : cannot convert from 'automation::ErrorLogger' to 'automation::ILogger *' 

Если я буду об этом неправильный путь, даже дизайн-мудрый, я учусь и с удовольствием слушать любые советы.

ILogger.h:

#ifndef _ILOGGER_H_ 
#define _ILOGGER_H_ 

namespace automation 
{ 
    class ILogger 
    { 
    public: 
     virtual void Log(const IError &error) = 0; 
    }; 
} 
#endif 

ErrorLogger.h:

#ifndef _ERRORLOGGER_H_ 
#define _ERRORLOGGER_H_ 
#include "ILogger.h" 
#include "IError.h" 

/* Writes unhandled errors to a memory-mapped file. 
* 
**/ 

namespace automation 
{ 
    class ErrorLogger : public ILogger 
    { 
    public: 
     ErrorLogger(const wchar_t * file = nullptr, const FILE * stream = nullptr); 
     ~ErrorLogger(void); 
     void Log(const IError &error); 
    }; 
} 
#endif 

ErrorLogger.cpp:

#include "stdafx.h" 
#include "ErrorLogger.h" 
#include "IError.h" 

using namespace automation; 

ErrorLogger::ErrorLogger(const wchar_t * file, const FILE * stream) 
{ 

} 

void ErrorLogger::Log(const IError &error) 
{ 
    wprintf_s(L"ILogger->ErrorLogger.Log()"); 
} 

ErrorLogger::~ErrorLogger(void) 
{ 
} 

IError.h:

#ifndef _IERROR_H_ 
#define _IERROR_H_ 

namespace automation 
{ 
    class IError 
    { 
    public: 
     virtual const wchar_t *GetErrorMessage() = 0; 
     virtual const int &GetLineNumber() = 0; 
    }; 
} 
#endif 

компиляции Ошибки:

enter image description here

Спасибо, -Francisco

+0

В C++ полиморфизм требует использования указателей (возможно, интеллектуальных указателей) или ссылок. –

+2

Ошибки компиляции нечитабельно малы. Можете ли вы поместить их в виде обычного текста вместо изображения? – PherricOxide

+2

Пожалуйста, разместите фактический код вместо изображений. –

ответ

2

ILogger * errorLogger = ErrorLogger(); errorLogger - указатель, вам нужно инициализировать его с помощью new operator.

Правильный способ определения базового указателя, который указывает на derieved класс является:

automation::ILogger * errorLogger = new automation::ErrorLogger(); 
//         ^^^^ 

Лучше использовать смарт-указатели в современном C++:

#include <memory> 
std::unique_ptr<automation::ILogger> errorLoggerPtr(new automation::ErrorLogger()); 

Кроме того, необходимо включить IError.h в ILogger.h

#include "IError.h" 

Другие предложения:

1 Использование fstream isntead из FILE 2 Использование станд :: wstring вместо wchar_t * 2 в CPP файле, то не»называют

using namespace automation; 

вместо завернуть определения функций с пространство имен, как то, что вы делали в заголовочном файле:

namespace automation 
{ 
    ErrorLogger::ErrorLogger(const std::wstring& file, std::ofstream& stream) 
    { 
    } 
} 

Точка не смешивает код C++ с кодом C, классы C++, такие как string, fstream предоставляют RAII, это безопаснее и проще в использовании.

+0

Спасибо @billz. Хотя это действительно работает, значит ли это, что я не могу инициализировать указатель ILogger на ErrorLogger в стеке? Потому что новое ключевое слово выделяет его в куче, не так ли? –

+0

Вы "#include" IError.h "в ILogger.h? – billz

+0

Да, я решил эту проблему. :) –

0

Вы должны #include "IError.h" в файле ILogger.h заголовка.

+0

А, это было глупо от меня. Как насчет моего другого вопроса? «быть в состоянии иметь переменные, типизированные для интерфейса. Однако следующее сообщение вызывает ошибки компиляции. Я думаю, что компилятор считает мой класс ErrorLogger абстрактным, потому что он наследуется от абстрактного класса или чего-то еще. ILogger logger = ErrorLogger() Если я собираюсь сделать это неправильно, даже разумно, я учусь и с удовольствием выслушаю все советы ». –

Смежные вопросы