7
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 перегруженные функции отправки, которые будут принимать объекты messageA и messageB.Шаблон множественного наследования Класс

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

Могу ли я узнать, почему существует неоднозначное? Разве не совсем очевидно, что для первого запроса на передачу я хочу позвонить в версию messageA? Для второго запроса отправки я хочу позвонить в версию 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 
+0

Обратите внимание, что неявное преобразование из 'messageA' в' messageA & 'не является стандартным C++; ссылка не const может быть привязана только к lvalue (http://msdn.microsoft.com/en-us/library/186yxbac(VS.80).aspx). Функция 'submit()' должна принимать 'const T &', а не 'T &'. –

ответ

11

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

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

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

Попробуйте добавить с помощью инструкций в ваших производных классах:

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

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

Re-сочинительства главным образом:

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

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

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

Примечание: Тем не менее, не компилятор, поэтому пытается мозг-отладки кода ... :-P ...

+0

«Я предполагаю, что одно наследование может скрыть другое». Нет. Компилятор будет использовать Koenig Lookup_ «Нет, это не так. «компилятор действительно нашел оба символа, но не может решить, что вызвать» «Да. – curiousguy

+0

«_temporaries (и, следовательно, const r-values) ._« Нет, временные константы ** не ** постоянны. – curiousguy

1
Something* smth1 = ((Base<Something> *)d)->createBase<Something>(); 

Приведенный выше код работает отлично.

+0

«' ((База *) d) «Уродливая и очень опасная: вы должны скрыть серьезную проблему с этим стилем C-стиля. OTOH, эта база Base & dBase = * d; Dbase.createBase (); 'безопасен. – curiousguy

Смежные вопросы