2015-06-29 1 views
1

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

class A 
{ 
public: 
    A() 
    { 
     cout << "Constructed A" << endl; 
    } 
    void DoAStuff() 
    { 
     cout << "Did A stuff" << endl; 
    } 
}; 

class I : public virtual A 
{ 
public: 
    I() 
    { 
     cout << "Constructed I" << endl; 
    } 
    void DoIStuff() 
    { 
     DoAStuff(); 
     cout << "Did I stuff" << endl; 
    } 
}; 

class B : public A 
{ 
public: 
    B() 
    { 
     cout << "Constructed B" << endl; 
    } 
    void DoBStuff() 
    { 
     cout << "Did B stuff" << endl; 
    } 
}; 

class C : public A, public I 
{ 
public: 
    C() 
    { 
     cout << "Constructed C" << endl; 
    } 
    void DoCStuff() 
    { 
     cout << "Did C stuff" << endl; 
    } 
}; 

class D : public A, public I 
{ 
public: 
    D() 
    { 
     cout << "Constructed D" << endl; 
    } 
    void DoDStuff() 
    { 
     cout << "Did D stuff" << endl; 
    } 
}; 

int main() 
{ 
    cout << "Creating a B" << endl; 
    B *b = new B(); 

    cout << "Creating a C" << endl; 
    C *c = new C(); 
    c->DoIStuff(); 

    cin.ignore(); 
    return 0; 
} 

В этом примере я имею BLASE класс A и 3-х классов, которые я хочу использовать полученные из A: B, C и D.

Оба C и D доля общего внедрения, которые я реализовал в отдельный класс I в DoIStuff(). Поскольку для этой реализации необходимо сделать материал, определенный в базовом классе A, I также наследует A. Ключевое слово virtual существует, так как мне нужен только один экземпляр A при создании C или D.

Это все кажется красивым и выразительным мне, однако, когда я пытаюсь скомпилировать это (с помощью VC++ компилятор VS 2008) Я получаю следующие 2 ошибки:

error C2584: 'C' : direct base 'A' is inaccessible; already a base of 'I' 
error C2584: 'D' : direct base 'A' is inaccessible; already a base of 'I' 

Чтобы получить эту работу с множественным наследованием, добавление класса «placeholder» (например, J), который наследует A (но ничего не делает), и наследование D и C этого класса, а не непосредственно от A, похоже, сработало. Однако этот класс placeholder делает код менее выразительным и усложняет понимание.

С другой стороны, я мог бы DoIStuff взять параметр A, что означает, что I не должны наследовать от A. Однако это означало бы, что мне придется перегружать DoIStuff как в D, так и в C.

Кто-нибудь знает, какое лучшее решение для совместного использования в этом сценарии?

+0

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

ответ

3

Вам нужно

1. class D : public virtual A, public I 

2. class C : public virtual A, public I 

В противном случае алмаз для множественного наследования не может быть настроена правильно.

Также ознакомьтесь с любопытно повторяющимся шаблоном шаблона. Это может быть приемлемой альтернативой.

+0

Ow, это довольно простое решение. CRTP выглядит интересно, но я думаю, что это сделает мой код более сложным, чем нужно. – Bitbored