2010-05-08 4 views
2

У меня есть следующая иерархия классовКак легко заменить базовый класс

class classOne 
{ 
    virtual void abstractMethod() = 0; 
}; 

class classTwo : public classOne 
{ 
}; 

class classThree : public classTwo 
{ 
}; 

Все classOne, classTwo и classThree абстрактные классы, и у меня есть еще один класс, определяющий чисто виртуальные методы

class classNonAbstract : public classThree 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

и сейчас мне это нужно по-другому ... Мне это нужно, как

class classNonAbstractOne : public classOne 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

class classNonAbstractTwo : public classTwo 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

и

class classNonAbstractThree : public classThree 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

Но все неабстрактные классы имеют те же самые новые методы, с тем же кодом ... и я хотел бы, чтобы не копировать все методы, и это код к каждому неабстрактному классу. Как я мог это сделать?

Надеюсь, это понятно ...

+0

Если они содержат один и тот же код, для чего нужны конкретные определения ClassTwo и ClassOne? – KillianDS

+0

ClassOne имеет пару виртуальных методов, которые перегружены в ClassTwo, а также ClassThree ... ClassNonAbstract просто добавляет определение к чистым виртуальным методам. – JTom

+0

представляет промежуточный класс с общей функциональностью или использует шаблоны для создания общего класса (шаблоны являются довольно сложными темами, вы должен будет прочитать о них, если вы их никогда не используете) – Anycorn

ответ

4
template<class Base> 
struct Concrete : Base { 
    void abstractMethod(); 

    void doIt() { 
    // example of accessing inherited members: 
    int n = Base::data_member; // or this->data_member 
    n = Base::method(); // non-virtual dispatch 
    n = this->method(); // virtual dispatch 

    // since Base is a template parameter, 'data_member' and 'method' are 
    // dependent names and using them unqualified will not properly find 
    // them 
    } 
    void doItToo(); 
}; 

typedef Concrete<classOne> classNonAbstractOne; // if desired, for convenience 

Убедитесь, чтобы дать свои абстрактные базовые классы либо виртуальный публичный деструктор или сделать деструктор защищенный (тогда он не должен быть виртуальным, но все еще может быть).

Поскольку шаблон должен быть проанализирован с именами смотрели без еще не зная точно, что Base будет, вам необходимо либо использовать Base::member или this->member доступ унаследованных членов.

1

Обычно я стараюсь избегать наследования (за исключением чистых абстрактных классов, которые определяют чистые интерфейсы), поскольку создает плотную связь. Во многих случаях композиция является лучшей альтернативой.

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

+0

Я сделаю +1 это. Состав> Наследование. Если doIt и doItToo имеют одинаковый код, тогда поместите их в базовый класс. ABC не обязательно должны быть всеми виртуальными чистыми методами - они могут быть обычными методами и членами. – Puppy

+0

Я не могу этого сделать, потому что мои чистые виртуальные методы предназначены для сетевых операций и поэтому зависят от платформы ... – JTom

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