Шаблонный класс множественного наследования

class messageA {
};

class messageB {
};

template<class T>
class queue {
public:
    virtual ~queue() {}
    void submit(T& x) {}
};

class A : public queue<messageA>, public queue<messageB>
{
};

int main()
{
    A aa;
    aa.submit(messageA());
    aa.submit(messageB());
}

Моя первая мысль, вышеупомянутый код должен быть прекрасным, поскольку класс A будет содержать 2 перегруженных отправить функции, которые примут объект messageB и messageA.

Однако компилятор дает мне следующую ошибку:

Я могу знать, почему существует неоднозначное? Разве это не, довольно очевидно, что, для 1-го отправляют вызов, я хочу назвать messageA версию? Поскольку 2-е отправляют вызов, я хочу назвать messageB версию?


------ Build started: Project: main, Configuration: Release Win32 ------
Compiling...
main.cpp
.\main.cpp(21) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(21) : error C3861: 'submit': identifier not found
.\main.cpp(22) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &'
        with
        [
            T=messageA
        ]
.\main.cpp(22) : error C3861: 'submit': identifier not found
7
задан curiousguy 14 May 2013 в 05:15
поделиться

1 ответ

У меня сейчас нет компилятора, но я предполагаю, что одно наследование может скрыть другое: компилятор будет использовать Koenig Lookup , чтобы найти правильный символ, и если я правильно помню , как только компилятор найдет подходящий символ (т. е. метод под названием «submit»), он прекратит поиск других в родительской и / или внешней областях.

В этом случае я думал, что оба наследующих класса будут искать символ, но без вашего точного компилятора (Visual C ++ 2003? 2008? 2010?) Я не могу предположить гораздо большего.

После некоторых размышлений другая возможность состоит в том, что компилятор нашел оба символа, но не может решить, какой из них вызвать (в момент разрешения символа компилятор заботится только об имени символа, а не его точном прототипе). Я считаю, что это последнее объяснение правильное.

Попробуйте добавить операторы using в производные классы:

class A : public queue<messageA>, public queue<messageB>
{
   using queue<messageA>::submit ;
   using queue<messageB>::submit ;
} ;

, чтобы перенести оба метода отправки непосредственно в область видимости класса A.

Также обратите внимание, что ваши методы отправки принимают сообщения как неконстантные ссылки, тогда как в конструкторе параметры ваших сообщений являются временными (и, следовательно, константными r-значениями).

Переписывание main как:

int main()
{
    A aa;
    messageA mA ;
    messageA mB ;
    aa.submit(mA);
    aa.submit(mB);
}

может помочь при компиляции (это может объяснить ошибку компилятора в строке 22).

Или вы можете изменить прототип ваших методов отправки, чтобы они принимали константные ссылки вместо неконстантных.

Примечание: все еще без компилятора, поэтому пытаюсь отладить ваш код мозгом ... :-P ...

11
ответ дан 6 December 2019 в 21:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: