2016-06-21 14 views
0

Обычно я пытаюсь найти ответы здесь, прежде чем что-либо публиковать, но я даже не уверен, как сформулировать мой вопрос.Наследование как интерфейса, так и реализации C++

Итак, вот что я хочу сделать ... Я хочу определить базовый интерфейс и производный интерфейс. Затем я хочу реализовать базовый интерфейс с дополнительными переменными и методами. Наконец, я хочу реализовать класс Derived из реализованного базового интерфейса, НО ТАКЖЕ, из производного интерфейса. Я не знаю о тебе, но у меня болит голова.

Если я делаю что-то вроде ниже, я получаю Неопределенные определения в коде DerivedFloat, так как этот код «видит» метод GetBaseValue из IBase, унаследованный через IDerivedFloat, а также GetBaseValue, унаследованный от Base.

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

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

template <typename VALUE_TYPE> 
class IBase 
{ 
public: 
    virtual VALUE_TYPE GetBaseValue() const = 0; 
}; 

class IDerivedFloat : public IBase<FLOAT> 
{ 
public: 
    virtual void SetBaseValue(const FLOAT & value) = 0; 
}; 

// Implementation of Base 
template <typename VALUE_TYPE> 
class Base : public IBase<VALUE_TYPE> 
{ 
public: 
    VALUE_TYPE GetBaseValue() const { return m_BaseValue; } 

protected: 
    VALUE_TYPE m_BaseValue; 
} 

// Uses expanded Base AND implements IDerivedFloat 
class DerivedFloat : public Base<FLOAT>, public IDerivedFloat 
{ 
public: 
    void SetBaseValue(const FLOAT & value) { m_BaseValue = value }; 
} 
+0

* Обычно я пытаюсь найти ответы здесь, прежде чем я что-нибудь опубликую * - Таким образом, вы не нашли «наследование бриллиантов» или [виртуальное наследование] (http://stackoverflow.com/questions/21558/in-c- what-is-a-virtual-base-class) в любом из ваших поисков? – PaulMcKenzie

+0

Не специалист в C++. Впервые я слышал о сроке наследования бриллиантов. Что касается «виртуального наследования», у меня есть. Но ясно, из вашего комментария, я не знаю, как к этой информации решить мою проблему. – ThermoX

+0

Вы нажали ссылку в своем комментарии? Это в основном дубликат ответа, который вы приняли. – PaulMcKenzie

ответ

3

Вы можете использовать virtual inheritance, чтобы обойти эту проблему:

class IDerivedFloat : virtual IBase<FLOAT> 
{ 
public: 
    virtual void SetBaseValue(const FLOAT & value) = 0; 
}; 

template <typename VALUE_TYPE> 
class Base : virtual IBase<VALUE_TYPE> 
{ 
public: 
    VALUE_TYPE GetBaseValue() const { return m_BaseValue; } 

protected: 
    VALUE_TYPE m_BaseValue; 
} 

Использование виртуального наследования дает Dérivé класс один экземпляр членов базового класса, а не один из каждого раз, когда он существует в иерархии классов.

+0

Спасибо Энди! Похоже, он делает то, что я хотел сделать ... И ваш ответ немного информативнее, чем «duh, разве вы не посмотрели на виртуальное наследование» :) – ThermoX

0

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

Пример:
- С наследует от A и B.
- A и B оба имеют добавить функцию().
- В C вы должны сказать A :: add() или B :: add(), чтобы сообщить компилятору, какой из них использовать.

Ссылка для деталей и более полной реализации: http://www.cprogramming.com/tutorial/multiple_inheritance.html

+0

Спасибо. Я действительно пытался это сделать! Но то, что меня беспокоило, заключается в том, что производный класс будет нести оба определения ... Которые я пытался избежать. Это приводит меня к выводу, что я, возможно, не подхожу к проблеме правильно, может быть? – ThermoX

+0

Единственная идея, которую я хотел бы сделать, если вы пытаетесь прекратить использовать обе функции, может быть, может переопределить их с помощью другой функции в самом дочернем элементе, но это не избавляет от функций родителя, просто покрывает их. Они все равно будут доступны. Я не уверен, что вы можете наследовать только части класса, вы должны наследовать его все или ничего. – Kadima

+0

Энди выше предоставил ответ. Еще раз спасибо за вашу помощь Кадима. – ThermoX

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