Я хочу понять 4 различных поведения модификаторов доступа в отношении наследования, когда речь идет о 4 комбинациях использования и/или пропуска template
s и ключевого слова this
. Весь следующий код выполнен в g++ 4.8:
Вот класс GrandChild
, который private
ly наследуется от Parent
, который private
ly наследуется от GrandParent
, который имеет public
enum
n
. Необъектный клиентский код может получить доступ к GrandParent::n
, потому что последний является public
enum
. Но GrandParent::n
недоступен изнутри GrandChild
:
#include <iostream>
using namespace std;
struct GrandParent { enum {n = 0}; };
struct Parent : private GrandParent { enum {n = 1}; };
struct GrandChild : private Parent {
enum {n = 2};
void f() {cout << GrandParent::n << endl;}
// ^ error: 'struct GrandParent GrandParent::GrandParent'
// is inaccessible
};
int main() {
cout << GrandParent::n << endl;
// ^ non-object access would have outputted `0` had `GrandChild`'s
// definition compiled or been commented out.
}
1.) Вызвана ли недоступность GrandParent::n
изнутри GrandChild
тем, что GrandChild
владеет базовым подобъектом GrandParent
, который скрывает необъектный доступ к GrandParent::num
и чья 2-генерационная private
ность делает недоступным базовый подобъект n
? Я ожидал, что сообщение об ошибке будет об этом.
2.) Но, видимо, это не так. Почему ошибка жалуется на конструктор GrandParent
?
3.) Добавление this->
к GrandParent::n
в определение f()
добавит ошибку, которую я ожидал в # 1, но не удалит жалобу ctor. Почему? Я предположил, что включение this->
является излишним и что его отсутствие приведет к тому, что поиск попытается найти n
подобъекта GrandParent
в пределах области действия GrandChild
перед не-объектом n
с менее непосредственной областью действия.
4.) Почему этот вариант шаблона компилируется? Функционально он похож на нешаблонный:
#include <iostream>
using namespace std;
template <unsigned int N>
struct bar : private bar<N - 1> {
enum {num = N};
void g() {
static_assert(N >= 2, "range error");
cout << bar<N - 2>::num << endl;
}
};
template <>
struct bar<0> { enum {num = 0}; };
int main() {
bar<2> b2;
b2.g(); // Output: 0
}
5.) Добавление this->
к bar<N - 2>::num
в определении g()
вызывает ошибку компилятора, которую я ожидал только в #1. Но почему он не включает ошибку № 2? И почему его упущение не приводит к ошибке №2?