Исправление неоднозначного вызова множественного наследования в C ++

У меня есть три класса, структурированные так:

#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;
}

5

Решение

Это из-за схема наследования алмазов, Чтобы устранить ошибку, вы можете указать конкретное пространство имен, из которого вы хотите, чтобы член понравился.

paddressType->MeasurementKeyword::GetValue()

или же

paddressType->CharacterKeyword::GetValue()

  1. В основном ваш AddressType класс имеет доступ к GetValue члены обоих классов, от которых он наследует и не может выбрать один (вызов неоднозначен).
  2. оператор разрешения области видимости (:: ) помогает указать, какой вы на самом деле хотите.
  3. Вы не сказали, что вы на самом деле хотите, чтобы этот код делал, поэтому я просто скажу, что, как правило, сложные шаблоны наследования не способствуют созданию читаемого кода, переосмыслите то, что вы действительно хотите.
15

Другие решения

Как правило, когда вы сталкиваетесь с смертельный алмаз смерти это признак того, что вы должны переосмыслить свой дизайн. Однако, если вы абсолютно не можете избежать этой ситуации, C ++ предлагает решение в виде виртуальное наследство. Виртуальное наследование устраняет некоторые «алмазные двусмысленности», но оно также неуклюже. Например, вы должны явно вызывать конструкторы, отличные от родительских, в конструкторе производного класса.

Еще раз, лучший способ состоит в том, чтобы избежать алмаза во-первых. Я программировал на C ++ много лет, и до сих пор у меня никогда не было этой проблемы в моем коде.

3

определить AddressType следующим образом:

class AddressType : public CharacterKeyword, public MeasurementKeyword
{
public:
using MeasurementKeyword::GetValue;
private:
float address;
float addresExt;
};
3
По вопросам рекламы [email protected]