Путаница в понимании вызова виртуальной функции и зависимого базового класса

#c #templates #inheritance #name-lookup #qualified-name

#c #шаблоны #наследование #поиск по имени #квалифицированное имя

Вопрос:

Я читаю полное руководство по шаблонам электронных книг и вопрос, который я собираюсь задать, может показаться вам глупым, но..

В этом 9.4.2 есть раздел зависимых базовых классов, который я не могу понять.

Вот частичный текст из него: http://tinypaste.com/633f0

 // Variation 2: 
template<typename T> 
class DD2 : public Base<T> { 
  public: 
    void f() { Base<T>::basefield = 0; } 
}; 
  

Мне нужна помощь в визуализации строки (или проблемной области) в тексте выше «С этим решением необходимо соблюдать осторожность, потому что, если для формирования вызова виртуальной функции используется неквалифицированное независимое имя, то квалификация блокирует механизм виртуального вызова и значение программы меняется. Тем не менее, бывают ситуации, когда первый вариант не может быть использован, и эта альтернатива подходит «

Я понимаю неквалифицированное независимое имя и т. Д., Но смешивание их с вызовом виртуальной функции — это то, что ускользает от меня.

Комментарии:

1. Это ужасное предложение, не так ли, этот код, похоже, предназначен для обеспечения невиртуального полиморфного поведения. Т.е. ваш производный класс может переопределять методы в вашем базовом классе, но поиск выполняется во время компиляции. Я подозреваю, что «Запрещение» в этом смысле означает, что вы не получите обычный динамический поиск во время выполнения на основе vtable….

2. Требуется больше контекста. Какую проблему пытается решить этот код?

Ответ №1:

Если квалифицированное имя (базовое поле) является виртуальной функцией, то квалификация запрещает виртуальный вызов. Это почти то же самое, как если бы у вас:

 struct Base {
  virtual void vCall() { }
};

struct Derived : public Base {
  virtual void vCall() { }
};

int main() {
  Derived d;
  Base* inst = amp;d;
  inst->Base::vCall(); // By qualifying we won't get virtual dispatch;
                       // this calls Base::vCall directly
}
  

Ответ №2:

Использование квалифицированного идентификатора class-name::function() препятствует виртуальности function , поэтому вместо этого следует использовать this->function() .

Это также работает для элементов данных : this->basefield .