В чем преимущество CRTP в C++ по сравнению с финальной или невиртуальной функцией?C++

Программы на C++. Форум разработчиков
Anonymous
В чем преимущество CRTP в C++ по сравнению с финальной или невиртуальной функцией?

Сообщение Anonymous »

Я новичок в изучении современного программирования на C++. Я прочитал много блогов и вопросов, но не нашел ответа на этот вопрос. В чем преимущество CRTP в C++ по сравнению с финальной или невиртуальной функцией?
Когда люди говорят о CRTP, в качестве примера часто приводят такой код:

Код: Выделить всё

template
class Base {
public:
void interface() {
static_cast(this)->implementation();
}

void foo() { ... }
};

class Derived : public Base {
public:
void implementation() { ... }
};

int main() {
Derived d;
d.interface();
d.foo();
}
Объект d класса Derived может использовать функцию foo из Base, а Derived перезаписывает функцию интерфейс. Они не ищут vtable, потому что это не виртуальная функция.
Но я думаю, что, когда я использую наследование, я могу добиться того же эффекта.
< pre class="lang-cpp Prettyprint-override">

Код: Выделить всё

class Base1 {
public:
virtual void interface() = 0;

void foo() { ... }
};

class Derived1 : public Base1 {
public:
void interface() final { ... }
};

int main() {
Derived1 *d1 = new Derived1();
d1->interface();
d1->foo();
}
В этом коде, когда d1 вызывает функцию интерфейса(), хотя функция является виртуальной функцией, компилятор может распознать, что на самом деле это функция класса Derived1, потому что я отмечаю окончательный. И d1 также может вызывать функцию foo из Base1 без поиска в vtable, поскольку foo не является виртуальной функцией.
Но в данном случае , я не использовал полиморфизм. Но Base — это класс-шаблон. Это Base. На самом деле у нас есть информация о том, что это производное, и мы не можем использовать общий указатель Base*, который указывает на Base и Base одновременно время. Я считаю, что сравнивать его и Base* в наследовании несправедливо. Его следует сравнивать с Derived при наследовании. Я имею в виду, что когда мы можем получить тип Base, мы также можем получить тип Derived*.
Тогда, на мой взгляд, разница между этими двумя способами переписывания и совместного использования общего кода есть только то, что наследование добавит виртуальную таблицу в заголовок производного класса. Таким образом, эти два способа могут иметь некоторые различия в использовании памяти и скорости работы из-за разных размеров памяти. Эта память используется, чтобы помочь нам указать подкласс через указатель родительского класса и выполнить вызовы виртуальных функций, когда нам это нужно. Если такой ситуации в коде нет, выбираем CRTP, иначе наследуем.
Правильна ли моя идея? Что еще может делать CRTP, чего не может наследование?

Подробнее здесь: https://stackoverflow.com/questions/786 ... ge-of-crtp

Вернуться в «C++»