Я решил проверить один из примеров в «Эффективном C++», и я не получаю ожидаемого результата. Таким образом, по-видимому, это (упрощенный) код не должен составлять:Почему я могу вызвать метод класса базового шаблона из производного класса
template <class T>
struct A {
void f(){}
};
template <class T>
struct B : public A <T> {
void f2() { f(); } // calling base function - will not compile
};
Вот объяснение (имена классов изменены для простоты):
Кода выше не будет компилироваться, по крайней мере, с совместимым компиляторы. Такие компиляторы будут жаловаться, что
f
не существует. Мы видим, чтоf
находится в базовом классе, но компиляторы там его не ищут.Нам нужно понять, почему. Проблема заключается в том, что когда компиляторы сталкиваются с определением для шаблона класса
B
, они не знают, на каком классе он наследует. Конечно, этоA<T>
, ноT
- это параметр шаблона, тот, который не будет известен до позже (когда создается экземплярB
). Не зная, чтоT
есть, нет способа узнать, что выглядит классA<T>
. В частности, нет способа узнать, имеет ли он функциюf
.
Мой компилятор (Visual Studio) не против ... Он даже не показывает никаких предупреждений.
Является ли приведенный выше код правильным или нет?
f() должно быть полностью квалифицировано с именем базового класса или 'this->' – goji
@Troy "f() должно быть полностью квалифицированным .." извините, что это значит? – Oleksiy
@Oleksiy Он работает на MSVC, потому что этот компилятор не реализует двухфазный поиск имени и, следовательно, не пытается разрешить зависимые имена до создания шаблона. Во время создания экземпляра 'A :: f' больше не является зависимым именем, так как слово' T' известно. И * полностью квалифицированный * означает, что он будет работать, если вы напишете 'A :: f()'. C++ - faq объясняет ловушки использования этого подхода. –
Praetorian