CRTP может вызывать метод дочернего класса, например виртуальную функцию, хотя виртуальная функция разрешается во время выполнения.

Насколько я знаю, вызывать виртуальную функцию в деструкторе небезопасно. Верно ли то же самое и для CRTP? Безопасно или небезопасно вызывать дочерний метод с помощью CRTP?

Редактировать:

Если это не небезопасно, как насчет случая множественного наследования? Например,

template<typename T, typename V>
struct CRTP {
    ~CRTP()
    {
        static_cast<V*>(static_cast<T*>(this))->run();
    }
};

struct Run {
    void run() { std::cout << "run" << std::endl; }
};

struct A : Run, CRTP<A, Run> {

};

Здесь порядок уничтожения A-> CRTP-> Run. Безопасно ли вызывать функции Run в деструкторе CRTP?

0
xylosper 26 Апр 2018 в 15:00

1 ответ

Лучший ответ

Насколько я знаю, вызывать виртуальную функцию в деструкторе небезопасно. Верно ли то же самое и для CRTP? Безопасно или небезопасно вызывать дочерний метод с помощью CRTP?

Это небезопасно. Применяются те же соображения. В конструкторе или деструкторе еще нет производного объекта / больше нет. Таким образом, вызов его функции-члена, будь то CRTP или обман с виртуальными функциями и косвенное обращение через невиртуальные элементы, приводит к неопределенному поведению.

К сожалению, ваш второй пример все еще имеет неопределенное поведение. Вы не можете static_cast<>(this) ни на что иное, кроме на cv-квалифицированный void или void*, или на базу (которой не является Run).

7
StoryTeller - Unslander Monica 26 Апр 2018 в 14:46