2014-09-11 5 views
1

Предположим, что у меня есть класс SecondTimer, который отсчитывает секунды и уведомляет слушателя, если предположить, что слушатель имеет специальный метод onTimer(), которые принимают события от таймера:Понимание C++ Пример шаблона

template <class TName> 
class SecondTimer 
{ 
public: 
    SecondTimer() : listener(nullptr), stime(0), time(1000), isStarted(false) {} 

    void init(TName * _listener, int _stime) 
    { 
     GASSERT(_listener && "The listener can not be NULL"); 
     listener = _listener; 
     stime = _stime; 
     time = 1000; 
     isStarted = false; 
     listener->onTimer(stime); 
    } 
    inline void start() { isStarted = true; } 
    inline void stop() { isStarted = false; } 
    void Process(int dtime) 
    { 
     if (!isStarted) 
      return; 

     time -= dtime; 
     if (time <= 0) 
     { 
      int ds = 1 - time/1000; 
      time = time % 1000 + 1000; 
      stime -= ds; 
      listener->onTimer(stime); 
      // 
      if (stime <= 0) 
      { 
       isStarted = false; 
      } 
     } 
    } 

private: 
    TName * listener; 
    int stime, time; 
    bool isStarted; 
}; 

Я хочу, чтобы использовать его в качестве шаблона для 1000 различные классы, которые реализуют функцию-член onTimer(int).

Что происходит, когда программа будет построена? Будет ли компилятор дублировать функции Init() и Process() для всех 1000 разных классов?

+0

Если ваш код действительно использует эти 1000 классов, да. Кроме того, если у вас есть такое количество классов, это означает, что вы действительно ошибаетесь в своем коде. –

+0

@JaviV: Я не думаю, что OP является actullay, создающим экземпляр шаблона 1000 раз. Они просто делают точку: будет ли компилятор тиражировать этот код в миллион раз? Или это будет умным? – rodrigo

+0

Я знаю, я имею в виду, что я уверен, что в таких случаях можно каким-то образом обобщить. –

ответ

3

Да. Компилятор будет экземпляр весь класс один раз для каждого класса, с которым вы его используете.

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

Есть несколько компиляторов (я не помню, какие из них, если они собираются скомпилировать две идентичные функции, байт-байт, они объединит их только в один. Это технически незаконно на C++, поскольку указатели на эти функции будут сравниваться с равными, если они не должны, но тогда многие функции из классов шаблонов будут объединены. К сожалению, в вашем примере будет использоваться только конструктор start() и stop(), так как другие используют класс шаблонов, поэтому, скорее всего, они будет генерировать другой код.

И для таких проблем вам нужно подумать, стоит ли использовать шаблоны или написать базовый класс с виртуальной функцией (интерфейсом). Существует компромисс между решением t он концептуально виртуальный вызывает onTimer во время выполнения (медленнее & меньше) или во время компиляции (быстрее & больше).

Например:

struct TName 
{ 
    virtual void onTimer() =0; 
}; 

class SecondTimer //no template bloat! 
{ 
    /*...*/ 
}; 

PS: Я собирался добавить некоторую информацию здесь о том, какие компиляторы слияния, но потом я обнаружил, что this answer объясняет это прекрасно.

+0

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

1

Будет ли дублировать функции Init() и Process() для всех 1000 разных классов?

Да. Это именно то, что произойдет. Компилятор будет создавать экземпляр всего кода для класса так же, как если бы вы все это вручную написали. Однако возможна некоторая оптимизация.

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