Наследование по доминированию - это действительно плохо? - PullRequest
19 голосов
/ 16 августа 2011

Я один из тех людей, которым нужно компилировать свой код с 0 предупреждениями. Обычно я уважаю компилятор и, если он выдает мне предупреждение, я воспринимаю это как знак того, что мне следует немного подправить свой код. Если я должен сказать компилятору игнорировать данное предупреждение, я немного дергаюсь.

Но этот, который я не могу обойти, и из того, что я могу сказать, я не сделал ничего "плохого". Кто-нибудь считает, что это плохой дизайн? Я не вижу в этом ничего особенно неприятного (кроме «злого бриллианта»), но это совершенно правильный и полезный код. Но он генерирует (в MSVC) предупреждение уровня 2!

class IFoo
{
public:
    virtual void foo() = 0;
};

class Bar : public virtual IFoo
{
public:
    virtual void foo() { std::cout << "Hello, world!"; }
};

class Baz : public virtual IFoo
{

};

class Quux : public Bar, public Baz
{

};

Теперь, если я создаю объект Quux, следует ожидать, что он вызовет реализацию Bar :: foo. MSVC очень полезен: он предупреждает меня за то, что я недостаточно двусмысленен?

предупреждение C4250: 'Quux': наследует Bar :: Bar :: foo 'через доминантность

Теперь я понимаю, что могу отключить это предупреждение с помощью прагмы, но это не тот вопрос, который я пытаюсь здесь задать. Есть ли какая-то причина, по которой я должен слушать компилятор здесь, или это просто чрезмерно усердное предупреждение?

Ответы [ 3 ]

11 голосов
/ 16 августа 2011

При выполнении виртуального наследования плохая идея не переопределять явно каждый член самого производного класса. Иначе, вы просите ваш код умереть ужасной смертью, когда кто-то меняет один из ваших базовых классов, который наследуется от виртуальной базы. В этом нет ничего активного , ваша программа не будет аварийно завершать работу или что-либо подобное, но это плохая идея для удобства обслуживания. Если вы хотите вызвать Bar::foo версию, то вам просто нужно делегировать ей Quux::foo.

2 голосов
/ 16 августа 2011

Что касается работоспособности вашего кода, просто напомню, что Bar является доминирующей реализацией foo.Это просто для того, чтобы проинформировать вас, на самом деле это не предупреждение, так что, если вы отлаживаете и думаете, что это Baz, вы не выдергиваете волосы :).

1 голос
/ 23 ноября 2011

Есть ли причина, по которой вы не пишете:

class Quux : public Bar, public Baz
{
    using Bar::foo;
};

Это дает вам тот же уровень повторного использования, без хрупкости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...