Я удивлен, что в следующем примере объявление частного класса Мидла делает это имя недоступным как тип в последующем выводе.
class Base {
public:
Base(Base const& b) : i(b.i) {}
int i;
};
class Middle : private Base { //<<<<<<<<<<<
public:
Middle(Base const* p) : Base(*p) {}
};
class Upper : public Middle {
public:
Upper(Base const* p) : Middle(p) {} //<<<<<<<<<<<
};
Таким образом, компиляция с g ++ (Debian 6.3.0-18 + deb9u1) 6.3.0 20170516 …
g++ -std=c++11 privateBase.cpp
Я получаю следующую диагностику:
privateBase.cpp:15:9: error: ‘class Base Base::Base’ is inaccessible within this context
Upper(Base const* p) : Middle(p) {}
^~~~
privateBase.cpp:1:12: note: declared here
class Base {
^
Ясно, что в тот момент, когда Base использовался в качестве базового класса Middle, его имя было доступно как тип. Я могу понять это, когда Base используется для обозначения хранилища базового класса, которое должно быть приватным. Но объявление частного базового класса делает имя типа недоступным, по крайней мере, неожиданным.
Это предназначено; увидеть основной вопрос 175, который даже добавил пример, иллюстрирующий это в [class.access.spec] p5:
[ Замечания: В производном классе поиск имени базового класса найдет
имя введенного класса вместо имени базового класса в
область, в которой это было объявлено. Имя введенного класса может быть меньше
доступнее, чем имя базового класса в области, в которой он
был объявлен. - конечная нота ] [ Пример:class A { }; class B : private A { }; class C : public B { A* p; // error: injected-class-name A is inaccessible ::A* q; // OK };
- конец примера ]
Это выпадает из взаимодействия между внедрением имени класса (для обоснования см. Почему вводится имя класса?) и тот факт, что в C ++ контроль доступа применяется после поиска имени, а не до.
Других решений пока нет …