设为首页 加入收藏

TOP

Member Function Templates(成员函数模板)
2014-11-23 23:21:08 来源: 作者: 【 】 浏览:2
Tags:Member Function Templates 成员 函数 模板

Member Function Templates翻译成中文就是成员函数模板,这个东西我个人见得少,最初是在STL的auto_ptr源代码里面看到的,当时候也不是很明白;这几天又翻了翻《More Effective C++》,正好看到上面介绍的比较详细,就找了点资料总结一下。
为了更好的说明问题,我们自己定义一个Smart Pointer(智能指针,这里只是示例,所以定义是不完整和不完善的),假设现在我们手上有这样三个类:MusicProduct、CD、MP3,类之间的关系图如下:

类图
我们定义的智能指针SmartPtr如下:

template
class SmartPtr
{
public:
explicit SmartPtr(T* realPtr = NULL) : pointee(realPtr){}

T* operator->() const
{
return pointee;
}

T& operator*() const
{
return *pointee;
}
private:
T* pointee;
};

现在有一个播放函数:

void displayAndPlay(const SmartPtr& pmp, int times)
{
for (int i = 1; i <= times; ++i)
{
pmp->displayTitle();
pmp->play();
}
}
如果有下面这样的调用,会不会有什么问题呢?

int main(int argc, char **argv)
{
CD *cd = new CD("BEYOND LIVE CD");
MP3 *mp3 = new MP3("BEYOND MP3");

SmartPtr cdMusic(cd);
SmartPtr mp3Music(mp3);

displayAndPlay(cdMusic, 10);
displayAndPlay(mp3Music, 10);

return 0;
}

实际编译时会发生错误,在Visual Studio 2008下面提示如下错误:

1>error C2664: “displayAndPlay”: 不能将参数 1 从“SmartPtr”转换为“const SmartPtr &”
1> with
1> [
1> T=CD
1> ]
1> and
1> [
1> T=MusicProduct
1> ]
1> ......
提示“SmartPtr”不能转换为“const SmartPtr &” 。因为在编译器眼里SmartPtr和SmartPtr是两个完全不相关的东西,他们之间没有继承关系。我们可以写一个隐式类型转换,但实际操作起来不太理想,正如前面所说,STL的auto_ptr采用了Member

Function Templates(成员函数模板)技术。我们可以再SmartPtr的定义中增加成员函数模板实现代码,具体如下:

template
class SmartPtr
{
public:
explicit SmartPtr(T* realPtr = NULL) : pointee(realPtr){}

T* operator->() const
{
return pointee;
}

T& operator*() const
{
return *pointee;
}
// Member Function Templates
template
operator SmartPtr()
{
return SmartPtr(pointee);
}
private:
T* pointee;
};
之后就可以正常编译和运行了。看起来很神奇吧,看看《More Effective C++》对此的解释:
现在请你注意,这可不是魔术——不过也很接近于魔术。假设编译器有一个指向 T 对象的智能指针,它要把这个对象转换成指向“T 的基类”的智能指针。编译器首先检查 SmartPtr的类定义,看其有没有声明明确的类型转换符,但是它没有声明。编译器然后检查是否存在一个成员函数模板,并可以被实例化成它所期望的类型转换。它发现了一个这样的模板(带有形式类型参数 newType) ,所以它把newType绑定成 T 的基类类型来实例化模板。 这时,惟一的问题是实例化的成员函数代码能否被编译:传递指针 pointee 到指向“T 的基类”的智能指针的构造函数,必须合法的。指针pointee 是指向 T 类型的,把它转变成指向其基类(public 或 protected)对象的指针必然是合法的,因此类型转换操作符能够被编译,可以成功地把指向 T 的智能指针隐式地类型转换为指向“T 的基类”的智能指针。
附注:
1. Member Function Templates是C++的一个新特性,可能有些编译器并不支持这个特性,比如VC6,编译时似乎完全忽略了我们新加入的Member Function Templates代码。仍然会提示如下错误:
--------------------Configuration: MftDemo - Win32 Debug--------------------
Compiling...
MemFunTmp.cpp
g:\w7documents\visual studio 6.0\projects\mftdemo\memfuntmp.cpp(87) : error C2664: 'displayAndPlay' :
cannot convert parameter 1 from 'class SmartPtr' to 'const class SmartPtr &'
Reason: cannot convert from 'class SmartPtr' to 'const class SmartPtr'

No constructor could take the source type, or constructor overload resolution was ambiguous
g:\w7documents\visual studio 6.0\projects\mftdemo\memfuntmp.cpp(88) : error C2664: 'displayAndPlay' :
cannot convert parameter 1 from 'class SmartPtr' to 'const class SmartPtr &'
Reason: cannot convert from 'class SmartPtr' to 'const class SmartPtr'
No constructor could take the source type, or constructor overload resolution was ambiguous
执行 cl.exe 时出错.

MftDemo.exe - 1 error(s), 0 warning(s)

作者“LoveBeyond”

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇浅谈面向对象语言的类型运算 下一篇初学GtkBuilder界面开发(重新整..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: