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
У меня сейчас нет компилятора, но я предполагаю, что одно наследование может скрыть другое: компилятор будет использовать 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 ...