现在的位置: 首页 > 综合 > 正文

模板多态

2013年07月25日 ⁄ 综合 ⁄ 共 2299字 ⁄ 字号 评论关闭

在C++中我们一般采用虚函数的方式实现函数的多态性,实现运行期绑定。
实际上我们也可以用模板来实现函数的多态性,这在ATL中大量使用的,请看如下的代码:

template<typename T,typename Deriving>
class Array...{
public:
         bool operator< (const Array<T,Deriving>& rhs)
         ...{return static_cast<Deriving*>(this)->Compare(rhs) < 0;}

         bool operator> (const Array<T,Deriving>& rhs)
         ...{return static_cast<Deriving*>(this)->Compare(rhs) > 0;}

         bool operator== (const Array<T,Deriving>& rhs)
         ...{return static_cast<Deriving*>(this)->Compare(rhs) == 0;}

protected:
         T m_rg[1024];
}
;

模板实例化:

class String : public Array<char,String>...{
public:
          int Compare(const Array<char,String>& rhs)
          ...{return strcmp(m_rg,rhs.m_rg);}
}
;

在实例化时,模板类接受了一个特殊的模板参数:派生类 的名字,我们还可以发现,在使用中将基类的指针强制转换成派生类的。这正是通过模板来实现多态性的地方,因为编译器在实例化派生类的同时展开基类的代码所以,因此,这是一个完全安全的向下转换,因此在编译时候,编译器就可以模板中的函数地址指向派生类的成员函数了,这样的优势是节省了虚函数表空间和查表时间。
       但这样也有个不好的地方是,破坏了“封装性”,父模板需要知道实例化类的方法,增加了耦合性(比如如果string类没有实现compare方法,则在编译器只能提示找不到compare方法,而不是提示string类应该实现compare方法),如果能够增加一个类似于纯虚函数的东东,只是负责让编译器进行编译期检查,并不实现虚函数就可以避免这样的问题了。

btw:这时ATL开发组“偶然”发现的一个特性,从一个侧面证明了泛型编程的强大和高效。不过这种仿动态绑定的方法只是用了c++标准和编译器的一个trip,因此在移植代码时需要谨慎考虑这种方法。  

 c++的模板是个很强很暴力的东西,可以轻松地模拟多态。下面举个例子:
====================================================================
#include <iostream>
#include <string>

using namespace std;

class StarDecorator//注意:与多态不同,不需要有类阶层(简单说不需要继承啥接口)
{
public:
    void
printHead()

    {
        cout
<< "**********" << endl;

    }
    void
printTail()

    {
        cout
<< "**********" << endl;

    }
};

class AddDecorator
{
public:
    void
printHead()

    {
        cout
<< "++++++++++" << endl;

    }
    void
printTail()

    {
        cout
<< "++++++++++" << endl;

    }
};

template<class Decorator>
class Printer
{
public:
    void
print(const string& str)

    {
        decorator.printHead();
        cout
<< str << endl;

        decorator.printTail();
    }
private:
    Decorator
decorator;

};

int main(int argc, char* argv[])
{
    Printer<StarDecorator>
p1;

    p1.print("Hello,World!");
   
    Printer<AddDecorator>
p2;

    p2.print("Hello,World!");

    return
0;

}
========================================
    是不是很像多态?更具体地说是设计模式中的Strategy模式。
    这么做的好处:
    1)比用多态时简单,不需要先构建Strategy对象再传入构造函数,故构造对象的代码简洁。
    2)灵活机动,不需要类阶层,只要实现相关接口就可以召之即来。如果没有实现相关接口会有明显的编译错误提示。
    这么做的缺点——和c++模板的缺点是一样的:
    1)易读性比较不好,调试比较困难
    2)模板只能定义在.h文件中,当工程大了之后,编译时间十分的变态。
   
    结论:有些场合可以让代码较简洁,但应避免在比较底层的地方使用。

抱歉!评论已关闭.