2010-05-08 2 views
6

Сценарий, создающий это, довольно сложный, поэтому я разберу несколько фрагментов и даю точное представление о соответствующих классах.Вопрос о множественном наследовании 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(); 
} 
}; 

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

ответ

2

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

Рассмотрим создание общего базового класса, который только определяет чистый виртуальный метод 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 в своей иерархии наследования. Это называется «dreaded diamond». Однако, если IBase и Base2 должны были наследовать практически от Stringable, как это:

class IBase : virtual public Stringable 
{ 
}; 

class Base2 : virtual public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

Тогда это говорит компилятору, что должно быть только один общего Stringable базового класса, даже если IBase и Base2 оба унаследованных одним класс, который именно вы хотите, потому что тогда Base2::toString используется для Class1.

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

1

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

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

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

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

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

  • Нет связанных вопросов^_^