У меня есть три класса, структурированные так:
#include <iostream>
using namespace std;
class Keyword
{
public:
virtual float GetValue() = 0;
};
class CharacterKeyword : public Keyword
{
public:
virtual float GetValue(){return _value;}
private:
float _value;
};
class MeasurementKeyword : public Keyword
{
public:
virtual float GetValue(){return _value;}
private:
float _value;
};
class AddressType : public CharacterKeyword, public MeasurementKeyword
{
private:
float address;
float addresExt;
};
int main()
{
AddressType *a = new AddressType();
a->GetValue();
return 0;
}
Я получаю следующее:
In function ‘int main()’:
error: request for member ‘GetValue’ is ambiguous
error: candidates are: virtual float Keyword::GetValue()
error: virtual float MeasurementKeyword::GetValue()
error: virtual float CharacterKeyword::GetValue()
Я немного изучил множественное наследование и знаю, что в нем много подводных камней, и это один из них. Мне нужно, чтобы моя структура классов была такой, поэтому мне было интересно, можно ли как-то исправить это с помощью шаблонов?
Обновить
После прочтения ваших комментариев моя первоначальная мысль заключалась в том, что, возможно, я могу просто провести различие между AddressType
это CharacterKeyword
и AddressType
это MeasurementKeyword
шаблонизируя AddressType
, И используя его как таковой в обновленном коде. ИЛИ ЖЕ Я могу просто указать пространство имен члена, которое я хотел бы. Поскольку шаблонный путь еще не был упомянут как ответ, это плохое решение? Должен ли я просто указать пространство имен члена, которого я хочу?
template <class T>
class AddressType : public T
{
private:
float address;
float addresExt;
};
int main()
{
AddressType<MeasurementKeyword> *a = new AddressType<MeasurementKeyword>();
a->GetValue();
return 0;
}
Это из-за схема наследования алмазов, Чтобы устранить ошибку, вы можете указать конкретное пространство имен, из которого вы хотите, чтобы член понравился.
paddressType->MeasurementKeyword::GetValue()
или же
paddressType->CharacterKeyword::GetValue()
AddressType
класс имеет доступ к GetValue
члены обоих классов, от которых он наследует и не может выбрать один (вызов неоднозначен). ::
) помогает указать, какой вы на самом деле хотите. Как правило, когда вы сталкиваетесь с смертельный алмаз смерти это признак того, что вы должны переосмыслить свой дизайн. Однако, если вы абсолютно не можете избежать этой ситуации, C ++ предлагает решение в виде виртуальное наследство. Виртуальное наследование устраняет некоторые «алмазные двусмысленности», но оно также неуклюже. Например, вы должны явно вызывать конструкторы, отличные от родительских, в конструкторе производного класса.
Еще раз, лучший способ состоит в том, чтобы избежать алмаза во-первых. Я программировал на C ++ много лет, и до сих пор у меня никогда не было этой проблемы в моем коде.
определить AddressType следующим образом:
class AddressType : public CharacterKeyword, public MeasurementKeyword
{
public:
using MeasurementKeyword::GetValue;
private:
float address;
float addresExt;
};