#c #inheritance #multiple-inheritance #compiler-warnings
Вопрос:
Первоначально базовый класс B был производным от класса A. Но поскольку C происходит как от A, так и от B, я получил неприятное наследование в форме ромба и, таким образом, удалил наследование в B, выбрав функцию преобразования в A.
Теперь я получаю предупреждения для классов типа C из-за того, что преобразование в базовые классы никогда не используется. Как я могу их исправить или удалить? Программа работает без проблем.
// base class providing most functionality
class A{
public:
int doStuff(){ return 0; };
};
// pure virtual interface providing a conversion to A
class B{
public:
virtual operator Aamp;()=0;
};
// interface implementation
class C: public A, public B{
public:
virtual operator Aamp;() override{return *this;}
};
предупреждение: функция преобразования, преобразующая «C» в его базовый класс «A», никогда не будет использоваться
virtual operator Aamp;() override{return *this;}
^
Комментарии:
1. А как насчет виртуального наследования вместо этого? Если и
B
то, и другое иC
фактически унаследуется отA
вас, в итоге получится одинA
экземплярC
sinlgle …2.
C c; Aamp; a = c;
не будет использовать вашoperator Aamp;
; возможно, возможно использование других имен.3.Может быть, еще проще: есть ли какая-то причина
B
, по которой не следует публично наследовать отA
? Если нет, просто сделайте это, и еслиC
затем он публично наследует отB
, онA
автоматически получает наследование, так почему же тогда он должен явно наследовать отA
снова?4. Потому что мой случай немного сложнее, когда C наследует не от A, а класс, производный от A вместо этого. Все различные классы типа C наследуются от другого класса, производного от A. Интерфейс B используется только в терминах методов, предоставляемых A.
5. Что ж, тогда вам следовало бы описать свою проблему как таковую:
D
наследование отB
иC
откуда оба последних наследуютA
. Но опять же: пустьB
иC
то, и другое фактически наследуется отA
вас, и вы в безопасности:D
получает один экземплярA
. Или это тот случай, когда вы не можете изменитьC
(как, очевидно, моглиB
бы )?
Ответ №1:
Учитывая экземпляр C
, ваш компилятор вполне способен преобразовать его в ссылку на A
, не нуждаясь в этой функции преобразования. Будет использоваться неявное преобразование, и эта перегрузка оператора никогда не будет использоваться, это буквально то, что говорит диагностика компилятора.
Если ваша цель здесь состоит в том, чтобы B
методы получили ссылку на связанный A
объект, то простое решение состоит в том, чтобы использовать для этого обычную функцию вместо перегруженного оператора:
class B{
public:
virtual Aamp; get_a()=0;
};
// interface implementation
class C: public A, public B{
public:
virtual Aamp; get_a() override{return *this;}
};
Другие методы B
просто нужно будет использовать get_a()
явно. Но, если вы так желаете:
class B{
public:
virtual Aamp; get_a()=0;
operator Aamp;() { return get_a(); }
};