Несмотря на то, что ваша проблема уже решена, я углубился в это и хотел бы исправить некоторую путаницу в отношении наследования.
Наследование используется, когда ваш класс имеет отношения «есть» с другим классом. Производный класс должен быть заменой для класса, от которого вы наследуете.
В вашем случае вы можете с уверенностью сказать, 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.