2011-10-10 108 views
2

对不起,这个愚蠢的问题,但我很新的C++。C++模板类和返回类型作为约束

我在我的项目中有一个叫做AlertInfoBase的基类。它有几十个子类。现在我想要一个类模板,它将有一个方法filter()。此方法将始终返回对AlertInfoBase的引用。代码如下:

template <class T> 
class AlertInfoFilter 
{ 
public: 
    AlertInfoFilter() { } 
    AlertInfoBase & filter(T & alertInfo) 
    { 
     return alertInfo; 
    } 
}; 

正如您所看到的,方法过滤器只是返回传递的参数。我的目标是使用模板专门化创建filter()的替代实现,但这不是我现在的问题/问题。 我面临的奇怪的事情是,当我将一个类的实例传递给filter()(从AlertInfoBase继承而来)时,一切都按预期工作。它返回相同的引用,但是当我传递一个不实现AlertInfoBase的类的实例时,该项目不会编译。其实这是我想要的那种行为,但有些澄清为什么发生这种情况会很好。编译器是否足够聪明地猜测,由于返回类型而使用不正确的参数填充方法?

谢谢

P.S.我正在使用MinGW编译器。

回答

5

您可以将模板视为代码生成机制。模板的特定实例在大多数情况下与手动编写的代码完全相同,只需在适当的位置替换模板参数即可。在你的榜样,如果你实例化AlertInfoFilterstd::string(如不从AlertInfoBase继承一个类的实例),然后将下面的代码是(约)产生:

class AlertInfoFilter_string 
{ 
public: 
    AlertInfoFilter_string() { } 
    AlertInfoBase & filter(std::string & alertInfo) 
    { 
     return alertInfo; 
    } 
}; 

显然,这不应该编译。

4

是的,编译器确实足够聪明,知道这一点。当T从AlertInfoBase下降并且无法在其他情况下将T转换为返回类型时,它使用从子类到基类的隐式转换。

它也可以与一个在不相关的类中实现operator AlertInfoBase&的类一起使用,但这只会增加混淆,所以我不建议这样做。

+0

我会非常感兴趣你将如何实现该操作符:)我可以想出一些有意思的方法,但除非类型为“is-a”或“has-a”AlertInfoBase,否则似乎并不适合:)(请注意,这是我在'答案'中暗示'可转换为'而不是'派生自') – sehe

+0

它也适用于共享单个AlertInfoBase的垫片。 – MSalters

0

filterT作为输入并将其转换为AlertInfoBase。如果T现在是不是AlertInfoBase的子类的类型,并且不提供转换,则无法编译该程序。

0

实际上,编译器做了一些接近代码的事情,用T代替实际参数并编译模板。对于您在程序中使用的每个不同的T,都会发生一次。

当你通过例如。一个int,你得到:

class AlertInfoFilter 
{ 
public: 
    AlertInfoFilter() { } 
    AlertInfoBase & filter(int & alertInfo) 
    { 
     return alertInfo; 
    } 
}; 

显然不能编译。