Мне интересно, что можно объявить интерфейс и реализовать интерфейс, используя множественное наследование.
Например.
Объявляю абстрактный класс для интерфейса.
class Interface{
public:
virtual int interf1(int a) = 0;
virtual int interf2(char c) = 0;
};
И чем реализовать эти два интерфейса, я определяю два класса для каждого, как показано ниже
class Implement1{
public:
int interf1(int a){
std::cout << a << a << std::endl;
return 0;
}
};
class Inplement2{
public:
int interf2(char c){
std::cout << c << c << c << std::endl;
return 0;
}
};
А затем в качестве последнего этапа я определяю класс, который наследует интерфейс и реализует все классы.
class Test : public Interface, public Implement1, public Inplement2{
};
Но, конечно, это не скомпилировано.
Есть ли способ создать такую функциональность?
И на самом деле я нашел какой-то способ, пытаясь скомпилировать его, как показано ниже, но я не уверен, что это безопасный способ, который не допускает потенциальных ошибок, даже если сейчас он работает, так как это простой код.
class Test : public Interface, private Implement1, private Inplement2{
public:
virtual int interf1(int a){
return Implement1::interf1(a);
};
virtual int interf2(char c){
return Inplement2::interf2(c);
}
};
Я предлагаю две альтернативы.
Определить два интерфейса, Interface1
с interf1
метод и Interface2
с interf2
метод. Определить две реализации Implement1
а также Implement2
которые наследуются от их соответствующего (единственного) интерфейса. Объедините их, наследуя от обоих Implement1
а также Implement2
,
Проблема в том, что вы не можете иметь общий интерфейс для использования в качестве полиморфного типа интерфейса.
Держите свой оригинал Interface
определение. Реализации оба должны фактически производные от интерфейса: class Implement1 : virtual public Interface { ... };
, Затем, при объединении этих реализаций, не производите снова от интерфейса, а только от двух ваших реализаций. Их суперкласс Interface
собирается слиться с одним (это то, что виртуальное наследование для, по сути, это также называется Diamond Inheritance).
Нет, нет способа переопределить виртуальную функцию, объявленную в базовом классе, за исключением повторного выделения ее в классе, производном от этого базового класса. Вам нужно будет объявить (и определить) Test::interf1
а также Test::interf2
как вы сделали в последнем примере.
Это означает, что нет никакой пользы от таких странных уловок с наследованием, чтобы обеспечить реализацию. Я бы использовал более простую композицию:
class Test : public Interface {
public:
virtual int interf1(int a){
return i1.interf1(a);
}
virtual int interf2(char c){
return i2.interf2(c);
}
private:
Implement1 i1;
Inplement2 i2;
};
Другая возможность — виртуальное наследование:
class Implement1 : public virtual Interface {
// implement interf1 here
};
class Inplement2 : public virtual Interface {
// implement interf2 here
};
class Test : public Implement1, public Inplement2 {
};
Но я не рекомендовал бы это без уважительной причины. Это увеличивает связь между интерфейсом и реализацией и, скорее всего, растопит мозг того, кто пытается выяснить, какие функции объявлены где.