Вопрос о множественном наследовании C++

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

/* 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();
 }
};

Это создает и связывается, но я понятия не имею, скрыло ли это ошибки.

6
задан Mr. Boy 8 May 2010 в 11:54
поделиться

2 ответа

Это должно работать нормально.

Вы правильно переопределяете интерфейс IBase, чтобы предоставить определение ToString () , которое будет перенаправлено до Base2 :: ToString () .

Обратите внимание, что Base2 не объявляет toString () как виртуальный, поэтому Class1 не может переопределить поведение Base2 :: ToString . Никакой двусмысленности.

И, кроме того, это не классическая алмазная проблема множественного наследования, решаемая виртуальным наследованием , потому что они не имеют общего базового класса.

1
ответ дан 17 December 2019 в 18:11
поделиться

Вы можете исправить это, используя "виртуальное наследование".

Рассмотрите возможность создания общего базового класса, который только определяет чисто виртуальный метод 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.

Ваша вторая идея не имеет "скрытых ошибок", но, как вы, вероятно, понимаете, ее повторная реализация является несколько хлопотной.

2
ответ дан 17 December 2019 в 18:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: