Есть ли способ сделать реализацию для абстрактного класса, который является множественным наследованием от других абстрактных классов в C ++? - PullRequest
0 голосов
/ 12 марта 2019

У меня есть два класса 'interface': AbstractAccess и AbstractPrint, и AbstractRun класс, наследующий от них и использующий их методы. Также у меня есть две реализации интерфейсов: Accessor для AbstractAccess и Print для AbstractPrint

#include <iostream>                                                                                                                                                                                                

using namespace std;                                                                                                                                                                                               

class AbstractAccess {                                                                                                                                                                                             
    public:                                                                                                                                                                                                        
    virtual string access (void) = 0;                                                                                                                                                                              
};                                                                                                                                                                                                                 

class AbstractPrint {                                                                                                                                                                                              
    public:                                                                                                                                                                                                        
    virtual void print (string) = 0;                                                                                                                                                                               
};                                                                                                                                                                                                                 

class AbstractRun : virtual public AbstractAccess, virtual public AbstractPrint {                                                                                                                                  
    public:                                                                                                                                                                                                        
        void run (void) {                                                                                                                                                                                          
            print(access());                                                                                                                                                                                       
        }                                                                                                                                                                                                          
};                                                                                                                                                                                                                 

class Accessor : virtual public AbstractAccess {                                                                                                                                                                   
    public:                                                                                                                                                                                                        
        string access (void){                                                                                                                                                                                      
            return name;                                                                                                                                                                                           
        }                                                                                                                                                                                                          

            void setName(string name) {                                                                                                                                                                                
            this->name = name;                                                                                                                                                                                     
        }                                                                                                                                                                                                          

    private:                                                                                                                                                                                                       
        string name;                                                                                                                                                                                               
};                                                                                                                                                                                                                 

class Print: public virtual AbstractPrint {                                                                                                                                                                        
    public:                                                                                                                                                                                                        
        void print (string s) {                                                                                                                                                                                    
            cout << s << endl;                                                                                                                                                                                     
        }                                                                                                                                                                                                          
};                                                                                                                                                                                                                 

Существуют ли способы приведения интерфейсов в AbstractRun к их реализациям или создания класса реализации Run, который будет использовать метод runR только в AbstractRun, но с реализованными интерфейсами?

1 Ответ

0 голосов
/ 13 марта 2019

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

Наследование используется, когда ваш класс имеет отношения «есть» с другим классом. Производный класс должен быть заменой для класса, от которого вы наследуете.

В вашем случае вы можете с уверенностью сказать, class Print это class AbstractPrint и class Access аналогично class AbstractPrint, поэтому наследование здесь хорошо.

С другой стороны, class AbstractRun - это , а не a AbstractPrint и ни AbstractAccess. AbstractRun просто обрабатывает / объединяет AbstractPrint и AbstractAccess. Это отношение следует абстрагировать с помощью агрегации (или композиции), в которой AbstractRun имеет ссылку / указатель на AbstractRun и AbstractPrint. Это сделало бы AbstractRun бетоном, поэтому давайте переименуем его в Runner.

class Runner
{
public:

    // We now need a constructor to set the references.
    Runner(AbstractAccess& access, AbstractPrint& print) : 
    accessor(access), printer(print) {}

    void run (void) {
        printer.print(accessor.access());          
    }

private:
    AbstractAccess& accessor; // has a AbstractAccess
    AbstractPrint& printer;   // has a AbstractPrint 
};

Теперь Access и Print могут быть определены как раньше.

Но давайте улучшим и их:

class Print: public virtual AbstractPrint {
    public:
        void print (string s) {                                                                                                                                                                                    
            cout << s << endl;                                                                                                                                                                                     
        }
};

Нам не нужно виртуальное наследование. Виртуальное наследование используется для решения алмазной проблемы. Но бриллианта больше нет, чем AbstractRunner был сделан конкретным классом. Итак, давайте удалим ненужные классификаторы.

class Accessor : public AbstractAccess {
    public:
        string access (void){
            return name;
        }

        void setName(string name) {
            this->name = name;
        }
    private:
        string name;
}; 

class Print: public AbstractPrint {
    public:
        void print (string s) {                                                                                                                                                                                    
            cout << s << endl;                                                                                                                                                                                     
        }
};

Кроме того, если у вас есть C ++ 11-совместимый компилятор, я бы предложил вам добавить квалификатор override для методов, которые переопределяют базовую функцию, чтобы иметь возможность определять методы, которые взяты из базового класса, а не .

class Accessor : public AbstractAccess {
    public:
        string access (void) override { //overrides  AbstractAcces method
            return name;
        }

        void setName(string name) { //does not override. is a method at Accessor level
            this->name = name;
        }
    private:
        string name;
}; 

Теперь при инициализации Runner нам нужно передать конкретные аксессоры и принтеры. Это можно сделать как:

// Somewhere in a .cpp - file

Accessor accessor;
Print printer;

Runner runner(accessor, printe);

runner.run(); //will call printer and accessor through the references.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...