2016-06-28 2 views
1

Я относительно новым для более продвинутых C++ показывает ... Так что имейте это в виду;)Скрытие конкретной реализации C++ интерфейс

Недавно я определил интерфейс для некоторого класса, состоящий, конечно, только чистые виртуальные функции.

Затем я реализовал конкретную версию этого интерфейса в отдельных файлах.

Вопрос ... Как мне вызвать конкретную реализацию этого Интерфейса с пользовательской стороны, не раскрывая внутренности этой конкретной реализации?

Так что, если у меня есть файл Interface.h заголовка, который выглядит следующим образом:

class Interface 
{ 
    public: 
    Interface(){}; 
    virtual ~Interface(){}; 
    virtual void InterfaceMethod() = 0; 
} 

Затем конкретный Implementation.h заголовочный файл, который выглядит следующим образом:

class Implementation : public Interface 
{ 
    public: 
    Implementation(){}; 
    virtual ~Implementation(){}; 
    void InterfaceMethod(); 
    void ImplementationSpecificMethod(); 
} 

Наконец, в main, У меня есть:

int main() 
{ 
    Interface *pInterface = new Implementation(); 
    // some code 
    delete pInterface; 
    return 0; 
} 

Как я могу сделать что-то подобное, не раскрывая детали Impleme ntation.h, от "main"? Разве нет способа сказать «главное» ... Эй, «Реализация» - это всего лишь тип «Интерфейса»; и хранить все остальное в отдельной библиотеке?

Я знаю, это должно быть быть дублирующим вопросом ... Но я не мог найти ясного ответа на это.

Спасибо за помощь!

+8

[функция Factory] (https://en.wikipedia.org/wiki/Factory_ (объект-oriented_programming)), что-то вроде 'интерфейс * MakeInterface () {вернуть новую реализацию; } '. Только объявление функции должно быть опубликовано в заголовке, и это само по себе не упоминает «Реализация» –

+0

@Igor Tandetnik Спасибо, Игорь. Если вы поместите это как ответ, я помету его, как ответ на кредиты. – ThermoX

+0

Не удаляйте вещи. Пойдите для умных указателей. – SergeyA

ответ

2

Вы можете использовать завод.

Заголовок:

struct Abstract 
{ 
    virtual void foo() = 0; 
} 

Abstract* create(); 

Источник:

struct Concrete : public Abstract 
{ 
    void foo() { /* code here*/ } 
} 

Abstract* create() 
{ 
    return new Concrete(); 
} 
+0

Спасибо! Я хотел бы отдать должное Игорю, так как он впервые поднял ответ. Но если он не представит полный ответ, я дам вам кредит. – ThermoX

0

Вы можете скрыть некоторые из внутренних данных (рядовых) вашего класса реализации из простого представления в файле заголовка, используя что-то вроде PIMPL, чтобы скрыть детали реализации в файле .cpp.

См. Is the pImpl idiom really used in practice? для более подробного обсуждения идиомы pimpl.

+1

Это, похоже, не отвечает на вопрос. OP не спрашивает, как скрыть детали реализации производного класса. Вместо этого они спрашивают, как избежать явного создания экземпляра производного типа из функции 'main' (т., функция 'main' знает только тип интерфейса, а не производный тип). –

+0

Спасибо @Shadowfen в любом случае. Я использовал подход Игоря. И я хотел бы дать ему кредит на ответ ... если бы он опубликовал его как полный ответ ... – ThermoX

0

Хотя завод решение подходит лучше вопрос ОП, я думаю, что версия Pimpl может решить те же проблемы тоже. Это немного более надуманным, но избегает виртуального интерфейса:

// Header file: 
class Interface 
{ 
    struct Implementation; 
    std::unique_ptr<Implementation> m_impl; 

    public: 
    Interface(); 
    ~Interface(); 
    void InterfaceMethod(); 
}; 

// Implementation file: 
class Interface::Implementation 
{ 
    public: 
    void ImplementationSpecificMethod() 
    { 
     std::cout << "Bla" << std::endl; 
    } 
}; 

Interface::Interface() 
    : m_impl(std::make_unique<Interface::Implementation>()) 
{ } 

Interface::~Interface() = default; 

void Interface::InterfaceMethod() 
{ 
    m_impl->ImplementationSpecificMethod(); 
} 

// Main file: 
int main() 
{ 
    Interface i; 
    i.InterfaceMethod(); // prints Bla 
} 
Смежные вопросы