Объявите интерфейс и реализуйте интерфейс, используя множественное наследование в переполнении стека

Мне интересно, что можно объявить интерфейс и реализовать интерфейс, используя множественное наследование.

Например.

Объявляю абстрактный класс для интерфейса.

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);
}
};

2

Решение

Я предлагаю две альтернативы.

1. Разделить интерфейс

Определить два интерфейса, Interface1 с interf1 метод и Interface2 с interf2 метод. Определить две реализации Implement1 а также Implement2 которые наследуются от их соответствующего (единственного) интерфейса. Объедините их, наследуя от обоих Implement1 а также Implement2,

Проблема в том, что вы не можете иметь общий интерфейс для использования в качестве полиморфного типа интерфейса.

2. Используйте виртуальное наследование для интерфейса

Живая демо

Держите свой оригинал Interface определение. Реализации оба должны фактически производные от интерфейса: class Implement1 : virtual public Interface { ... };, Затем, при объединении этих реализаций, не производите снова от интерфейса, а только от двух ваших реализаций. Их суперкласс Interface собирается слиться с одним (это то, что виртуальное наследование для, по сути, это также называется Diamond Inheritance).

2

Другие решения

Нет, нет способа переопределить виртуальную функцию, объявленную в базовом классе, за исключением повторного выделения ее в классе, производном от этого базового класса. Вам нужно будет объявить (и определить) 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 {
};

Но я не рекомендовал бы это без уважительной причины. Это увеличивает связь между интерфейсом и реализацией и, скорее всего, растопит мозг того, кто пытается выяснить, какие функции объявлены где.

3

По вопросам рекламы [email protected]