我想知道当我使用指定模板类型参数创建类模板的实例时
1)为什么非被调用的函数没有被实例化? 。
2)直到我尝试使用它们才编译?
3)这种行为背后的逻辑是什么?
示例
template <class T>
class cat{
public:
T a;
void show(){
cout << a[0];
}
void hello(){
cout << "hello() get called \n";
}
};
int main(){
cat<int> ob1; // I know that show() did not get instatiated, otherwise I will get an error since a is an int
ob1.hello();
}
答案 0 :(得分:6)
模板不是代码 - 它们是用于制作实际代码的模式。在提供参数之前模板不完整,因此无法提前创建代码。如果不使用一组特定的模板参数调用函数,则永远不会生成代码。
答案 1 :(得分:3)
如果他们实例化了整个班级,那么你可能会得到无效的代码。
你并不总是那么想。
为什么呢?因为在C ++中,它是困难(在某些情况下,根据我所知,完全不可能),“只有在X,Y和Z为真时才编译此代码”。
例如,您如何说,“只有我的复制构造函数,如果可以复制嵌入对象”?据我所知,你不能。
所以他们只是让他们不能编译,除非你真的打电话给他们。
答案 2 :(得分:3)
更多点缀:这通常称为duck typing,底线是它允许您编写“类模式”,其中某些成员函数在实例化时可能会应用使用一种模板类型时,其他成员可以在使用第二种模板类型进行实例化时应用,并且只需要实际调用的那些进行编译,您可以编写更少的代码用于最终的操作常见的。
通过不要求编译所有成员函数,您可以获得实际编译的函数的静态类型检查的所有细节。
例如,假设你有:
template <typename E>
class myContainer {
// Imagine that constructors, setup functions, etc. were here
void sort(); // this function might make sense only if E has an operator< defined
E max(); // compute the max element, again only makes sense with a operator<
E getElement(int i); // return the ith element
E transmogrify(); // perhaps this operation only makes sense on vectors
};
然后你有
// sort() and getElement() makes total sense on this, but not transmogrify()
myContainer<int> mci;
// sort and max might not be needed, but getElement() and transmogrify() might
myContainer<vector<double>> mcvd;
答案 3 :(得分:2)
没有为cat<int>::show()
生成代码,因为您从未调用它。如果您确实调用它,您将收到编译错误。永远不会调用的模板函数不存在。
模板只不过是测试替换机制。这使他们非常强大。作为程序员,您可能想要创建一个cat<int>
知道您永远不会调用show()
或调用任何其他无效的内容。编译器让你知道你是否这样做,所以它很好用。
所以,如果你的问题是“为什么会这样”,我会问你“为什么不”?这是一个设计选择。这个选择允许我安全地使用模板类型,并且仍然可以从代码的其他部分中受益。有什么危害?你也生成更少的代码,这是一件好事,对吗?