Следующий код C++ не компилируется:
class Val
{
protected:
int n;
public:
Val() : n(0) {}
Val(int nn) : n(nn) {}
virtual int blah() const = 0;
};
template <class T>
class subVal : public Val
{
public:
subVal() : Val() {}
int blah() const { return n; }
};
template <class T>
class subsubVal : public subVal<T>
{
public:
subsubVal() : subVal<T>() {}
int blah() const { return n; } // this is the "faulty" line
int blahblah() const { return n; }
};
subsubVal<int> ssv; // declare an instance, to confirm that it can be done
Компилятор (VisualStudio) говорит C2065 'n' необъявленный идентификатор.
Если я заменю строку, отмеченную ошибкой, на
int blah() const { return Val::n; } // replacement line
тогда компилируется нормально.
Неудача, я думаю, связана с тем, что Val здесь является абстрактным классом, поскольку еще один способ добиться успешной компиляции — это закомментировать объявление чистой виртуальной функции blah() в классе Val. Обратите внимание, что дочерний метод blahblah() не вызывает ошибки компиляции. Я также думаю, что это как-то связано с шаблонами, в том смысле, что код компилируется, если удалить шаблоны (но, конечно, я хочу использовать шаблоны в полном проекте; это просто фрагмент для иллюстрации). Обратите также внимание, что у дочернего элемента нет проблем с просмотром значения данных n в родительском элементе. Просто внук не видит этого без посторонней помощи.
Я надеюсь сначала на ответ, который проясняет логику (поскольку мой код, который не скомпилировался, кажется мне логичным), а затем на решение лучше, чем вставлять множество ужасных идентификаторов «Имя класса::» по всему коду внука. (На практике эти идентификаторы будут иметь более длинные имена и сильно снизят естественность и читабельность кода).