Сценарий, генерирующий это, довольно сложен, таким образом, я разделю несколько частей и дам точное представление включенных классов.
/* This is inherited using SI by many classes, as normal */
class IBase
{
virtual string toString()=0;
};
/* Base2 can't inherit IBase due to other methods on IBase which aren't appropriate */
class Base2
{
string toString()
{
...
}
};
/* a special class, is this valid? */
class Class1 : public IBase, public Base2
{
};
Так, действительно ли это допустимо? На toString будут конфликты? Или может Class1 использовать Base2:: toString для удовлетворения IBase? Как я говорю, что существует много других вещей, не показанных, таким образом, предложения для основных конструктивных изменений на этом примере, вероятно, не настолько полезны..., хотя любые общие предложения/совет приветствуются.
Моя другая мысль была чем-то вроде этого:
class Class1 : public IBase, public Base2
{
virtual string toString()
{
return Base2::toString();
}
};
Это создает и связывается, но я понятия не имею, скрыло ли это ошибки.
Это должно работать нормально.
Вы правильно переопределяете интерфейс IBase, чтобы предоставить определение ToString ()
, которое будет перенаправлено до Base2 :: ToString ()
.
Обратите внимание, что Base2
не объявляет toString () как виртуальный, поэтому Class1
не может переопределить поведение Base2 :: ToString
. Никакой двусмысленности.
И, кроме того, это не классическая алмазная проблема множественного наследования, решаемая виртуальным наследованием , потому что они не имеют общего базового класса.
Вы можете исправить это, используя "виртуальное наследование".
Рассмотрите возможность создания общего базового класса, который только определяет чисто виртуальный метод toString
(или, в действительности, чисто виртуальные версии любых методов, которые имеет смысл иметь и IBase
, и Base2
), например.
class Stringable {
public:
virtual string toString() = 0;
};
Затем, пусть и IBase
и Base2
наследуют от этого класса Stringable
:
class IBase : public Stringable
{
};
class Base2 : public Stringable
{
public:
virtual string toString()
{ ... }
};
Теперь это все равно не будет работать, потому что Class1
будет наследовать две копии базового класса Stringable
, только одна из которых имеет реализацию для toString
в своей иерархии наследования. Это известно как "страшный алмаз". Однако, если IBase
и Base2
наследуют virtually от Stringable
, вот так:
class IBase : virtual public Stringable
{
};
class Base2 : virtual public Stringable
{
public:
virtual string toString()
{ ... }
};
Тогда это говорит компилятору, что должен быть только один общий базовый класс Stringable
, даже если IBase
и Base2
наследуются одним классом, что именно то, что вы хотите, потому что тогда Base2::toString
используется для Class1
.
Ваша вторая идея не имеет "скрытых ошибок", но, как вы, вероятно, понимаете, ее повторная реализация является несколько хлопотной.