我知道C ++中模板的基础知识,但我仍在学习它。 我对以下代码有疑问:
#include <iostream>
using namespace std;
class PNG {
public:
static void draw() {
cout<<"PNG drawing"<<endl;
}
};
template <typename Image>
void draw() {
Image::draw();
}
int main() {
draw<PNG>();
}
函数draw()
,我将类型Image
传递给它,它将使用draw()
的{{1}}方法。
Image
在这里,我传递template <typename Image>
void draw() {
Image::draw();
}
并希望在Image
内使用draw()
方法,但模板函数Image
没有参数。所以我的问题是,如果我以这种方式在draw()
中调用此模板函数draw()
:main
是否允许?
模板函数draw<PNG>();
如何知道draw()
是一个类,以及如何调用类成员函数PNG
?
答案 0 :(得分:4)
您的第一个问题
如果我调用此模板函数 以这种方式在main中绘制draw():draw();是 它允许吗?
正如您已经意识到的那样,如果没有函数参数可以解决它,编译器本身不能推导你的意思是draw<PNG>
。
所以,你必须写(你已经做过):
int main() {
draw<PNG>();
}
您无法在此处省略模板参数。
您的第二个问题
以及模板函数如何绘制() 知道PNG是一类,怎么样 类成员函数draw()是 叫?
当使用参数PNG
实例化函数模板(A)时,生成的函数体看起来像(B):
// A:
template <typename Image>
void draw() {
Image::draw();
}
// B:
PNG::draw();
解析器知道,为了使其工作,PNG
必须是命名空间或类/结构。如果不是,则该函数将无法编译。
比如说你打电话给draw<int>()
,例如,你的代码会尝试拨打int::draw()
,这是不可能的。
现在,由于SFINAE(查找它!),您将不会因损坏的int::draw()
电话而收到编译错误;这种特殊的实例化将被禁止存在。你可能会被告知“函数draw()
没有匹配”,因为 - 对禁止的实例进行折扣 - 它可以选择使用的函数draw
不会超载。
答案 1 :(得分:3)
draw<PNG>();
PNG
将传递给模板参数Image
。因此,编译器会实例化相应的模板。换句话说,使用模板参数Image
生成的函数将被调用参数PNG
替换。
由于PNG::draw()
是静态成员函数,因此不需要实例来调用它。所以,
Image::draw(); => PNG::draw() ; // Template parameter substituted and the call
// is made.
答案 2 :(得分:-1)
您不能简单地在主函数中调用draw()
,如下所示:
draw();
您需要将其用作模板函数或成员函数。
PNG dummy;
dummy.draw(); // Okay.
dummy::draw(); // Okay.
draw<PNG>(); // Okay.
draw(); // Not okay.
我不确定你的第二个问题是什么意思。在这种情况下,typename
关键字表示该函数将接受恰好具有draw()
成员的未知类型的对象。