C ++多态与模板接口

时间:2012-02-01 19:41:58

标签: c++ templates polymorphism

Timer.h:

template<class T>
class Timer {
    public:
      typedef T Units;

    virtual Units get() = 0;
};

TimerImpl.h:

class TimerImpl: public Timer<long> {
public:

TimerImpl() {
}

~TimerImpl() {

}

long get();

};

FpsMeter.h(版本1):

template <class T> 
class FpsMeter {
    private:
    Timer<T>* timer;

    public:
    FpsMeter (Timer<T>* timer) {
        this->timer = timer;
    }

    ...

};

此示例有效。但它看起来并不漂亮。

Timer<long>* t = new TimerImpl();
FpsMeter<long>* f1  = new FpsMeter<long> (t);

这里有很多额外的模板用法。当类型由实现定义并且用户类没有定义新类型时,我怎样才能实现multy-type接口的这个想法,它应该使用实现的类型。

4 个答案:

答案 0 :(得分:1)

据我所知,这是你在C ++中可以做的最好的事情。 FpsCounter需要知道类型T,以便它知道它可以接受哪些Timer<T>实现。您的示例代码可以更简单一些:

FpsMeter<long>* f1  = new FpsMeter<long> (new TimerImpl());

...至少让您不再重复模板类型,但当然在这种情况下,FpsMeter必须负责删除TimerImpl,最好通过auto_ptr或这样

我也要问,你是否真的需要改变get()的回报值。除long之外,您希望它返回什么样的值?

答案 1 :(得分:1)

如果你不介意总是在堆上创建FpsMeter的辅助模板函数,你可以像下面这样的

template < class T >
FpsMeter<T> *make_FpsMeter( Timer<T> *timer ) {
  return new FpsMeter<T>( timer );
  }

然后创建适当类型的FpsMeter就像这样

FpsMeter<long> *f1 = make_FpsMeter( new TimerImpl() );

或者,如果您可以使用C ++ 11 auto,那么

auto f1 = make_FpsMeter( new TimerImpl() );

答案 2 :(得分:1)

也许你可以从C ++ 11的<chrono> library中获取灵感(也可以在boost中获得)。或者更好的是,节省一些时间并直接使用它。它高效,安全,灵活且易于使用。

答案 3 :(得分:0)

如果你想只使用基于机器计时器实现的计时器(应该在编译阶段为我假设的整个程序定义),我只需要使用typedef和一些预处理器魔术来实现它:

[...]
#if TIMER_LONG // Here you should somehow check what type is used on target platform.
    typedef Timer<long> implTimer;
    typedef FpsMeter<long> implFpsMeter;
#else // If eg. using double?
    typedef Timer<double> implTimer;
    typedef FpsMeter<double> implFpsMeter;
#fi

这应该使用户代码不知道所使用的实际类型,只要它使用implTimer和implFpsMeter。

如果您的意思是代码的某些部分将使用不同的TimerImpl,那么您应该使FpsMeter类具有多态性

class FpsMeter{
public:
    virtual double fps()=0;
    virutal void newFrame()=0;
    [...]
    //Class counts new frames and using internal timer calculates fps.
};

template <typename T>
class FpsMeterImpl: public FpsMeter{
    TimerImpl<T>* timer;
public:
    FpsMeterImpl(TimerImpl<T>* timer);

    virtual double fps();
    virutal void newFrame();
};