2014-12-29 20 views
0

Я в настоящее время возился с шаблоном CRTP с использованием шаблонов C++. В то время как возиться с визуальной студией, я нашел несколько способов/методов, в которых производный класс может вызывать реализацию функции базового класса. Ниже приведен код, который я использую, а также 3 строки с комментариями, показывающие, как вызвать реализацию базового класса функции из производного класса. Есть ли преимущество в использовании одного метода над другим? Есть ли различия? Каков наиболее распространенный метод?CRTP - Как вызвать реализацию базового класса метода из производного класса?

template<typename T> 
struct ConsoleApplication 
{ 

    ConsoleApplication() 
    { 
     auto that = reinterpret_cast<T*>(this); 
     that->ShowApplicationStartupMsg(); 
    } 



    void ShowApplicationStartupMsg() 
    { 

    } 
}; 


struct PortMonitorConsoleApplication : ConsoleApplication <PortMonitorConsoleApplication> 
{ 
    void ShowApplicationStartupMsg() 
    { 
     // __super::ShowApplicationStartupMsg(); 
     // this->ShowApplicationStartupMsg(); 
     // ConsoleApplication::ShowApplicationStartupMsg(); 
    } 
}; 
+0

Почему базовые и производные классы должны иметь значение 'ShowApplicationStartupMsg()'? Если производный ничего не делает, кроме вызова базы, вы должны опустить версию в производном классе. – willj

+1

Только один из этих трех является действительным способом вызова скрытого базового метода. – hvd

+1

Конструктор базового класса имеет неопределенное поведение. База находится в процессе инициализации, но ни один из членов производного экземпляра и ни один из его членов еще не инициализирован. Вы вызываете объект, который еще не был полностью инициализирован. Вы также не должны использовать 'reinterpret_cast' здесь, вместо этого используйте' static_cast'. –

ответ

1

Предпочтительный метод, который я видел, чтобы использовать эту функцию:

ConsoleApplication::ShowApplicationStartupMsg();

Это хорошо, так как это очень ясно, что вы пытаетесь сделать, и то, что родительский класс метод называют это from (особенно полезно, если вы не являетесь родительским классом, является производным классом).

0
ConsoleApplication <PortMonitorConsoleApplication>::ShowApplicationStartupMsg(); 

Используйте полное имя базового класса.

Обратите внимание, что this-> ShowApplicationStartupMsg() не вызывает вашу базу, он снова вызывает вашу собственную функцию.

__super не является стандартным (и не должен становиться одним, поскольку он неоднозначен с несколькими основаниями).

Использование ConsoleApplication :: не является полностью стандартным (хотя я считаю, что GCC принимает его), поскольку вы не наследуете от ConsoleApplication per se, а всего лишь один конкретный экземпляр этого.

+0

«Использование ConsoleApplication :: не является полностью стандартным» - на самом деле. Язык все равно будет иметь смысл, если бы он был определен так, как вы думаете, это просто так не определяется таким образом. :) Посмотрите вверх, «впрысните-класс-имя», если хотите. – hvd

+0

Будет делать - потому что я знаю, что у нас есть несколько отчетов об ошибках на работе, потому что это не скомпилировалось на каком-то компиляторе. – dascandy

Смежные вопросы