Требуется это пространство имен при обращении к базовому классу
-
28-09-2019 - |
Вопрос
У меня такой код:
namespace N {
class B {
public:
virtual void doStuff(B *) = 0;
};
}
// not in a namespace
class Derived : public N::B {
public:
void doStuff(B *); // Should this be N::B, or is B ok?
};
Нужна ли мне квалификатор пространства имен, в котором выводятся базовый класс? GCC и MSVC довольны кодом, как написано, но другой компилятор жалуется, если я не помещаю пространство имен. Что говорит стандарт C ++?
Решение
Внутри класса определение B в порядке. Это так называемый Инъекционное имя класса.
Это также относится к шаблонам (не подсчитание зависимых оснований). Например
template <class T> class B{};
template <class T> class C: public B<int>
{
void f(B* p) {} //same as B<int>* p
void f(C* p) {} //same as C<T>* p
};
В целом базовый класс (и сам класс) можно упомянуть внутри определения класса без квалификации или шаблонных аргументов.
Цитаты из стандарта:
9.2: имя класса вставляется в объем, в котором он объявляется сразу после видимого класса. Имя класса также вставляется в объем самого класса; Это известно как введенное имя-класс. В целях проверки доступа - имя впрыскиваемого класса рассматривается как если бы это было название государственного участника.
Из этого определения следует, что имя самого класса публично доступно из класса, и, следовательно, доступно в полученных классах. Что доказывает, что моя точка о B, которая в порядке наряду с N :: B, потому что имя B унаследовано
Кстати, это также объясняет, почему следующее неверно:
template <class T> class B{};
template <class T> class C: public B<T>
{
void f(B* p){} //ERROR
// the above is invalid!! Base class is dependent therefore
//its scope is not considered during unqualified name lookup
void g(typename C::B* p){} //this is valid, same as B<T>* p
};
14.6.1 говорит о приведенных именах классов в шаблонах. Здесь слишком долго вставлять. Емкость