面试题答案
一键面试实例化过程
-
普通函数:普通函数在被调用时才进行实例化(如果是函数模板)。编译器会根据调用处传入的实参来推导模板参数,进而实例化出具体的函数。
template <typename T> void normalFunction(T t) { std::cout << "Normal function with value: " << t << std::endl; } int main() { normalFunction(10); // 此处实例化 normalFunction<int> return 0; }
分析:在
main
函数中调用normalFunction(10)
时,编译器根据传入的int
类型实参,实例化出normalFunction<int>
。 -
static
函数(这里指类模板中的static
成员函数模板):static
成员函数模板在其被使用时实例化,包括被显式调用或者取其地址等情况。template <typename T> class MyClass { public: static void staticFunction(T t) { std::cout << "Static function with value: " << t << std::endl; } }; int main() { MyClass<int>::staticFunction(20); // 此处实例化 MyClass<int>::staticFunction<int> return 0; }
分析:通过
MyClass<int>::staticFunction(20)
调用static
成员函数,编译器实例化出MyClass<int>::staticFunction<int>
。即使MyClass<int>
类没有实例化对象,只要使用了static
成员函数,就会进行实例化。
作用域规则
-
普通函数:普通函数模板的作用域通常是其声明所在的作用域,一般是全局作用域或者某个命名空间作用域。如果在命名空间内声明,其作用域局限于该命名空间。
namespace MyNamespace { template <typename T> void normalFunction(T t) { std::cout << "Normal function in namespace with value: " << t << std::endl; } } int main() { MyNamespace::normalFunction(30); return 0; }
分析:
normalFunction
在MyNamespace
命名空间内声明,其作用域局限于MyNamespace
,在main
函数中需要通过命名空间限定来调用。 -
static
函数:static
成员函数模板属于类模板,其作用域在类模板的作用域内。它可以通过类模板名或者类模板实例名来访问。template <typename T> class MyClass { public: static void staticFunction(T t) { std::cout << "Static function in class with value: " << t << std::endl; } }; int main() { MyClass<int>::staticFunction(40); MyClass<int> obj; obj.staticFunction(50); // 也可以通过对象调用,但实际调用的还是类的 static 函数 return 0; }
分析:
staticFunction
属于MyClass
类模板,通过MyClass<int>::staticFunction
或obj.staticFunction
(obj
为MyClass<int>
的实例)来调用,其作用域在MyClass
类模板内。
对类型推导影响
-
普通函数:普通函数模板的类型推导完全依赖于调用时传入的实参。编译器根据实参的类型来确定模板参数的类型。
template <typename T> void normalFunction(T t) { std::cout << "Normal function type: " << typeid(t).name() << std::endl; } int main() { int num = 10; normalFunction(num); // 推导出 T 为 int double dnum = 20.5; normalFunction(dnum); // 推导出 T 为 double return 0; }
分析:根据传入的
int
类型变量num
和double
类型变量dnum
,编译器分别推导出T
为int
和double
。 -
static
函数:static
成员函数模板同样依赖于调用时传入的实参进行类型推导,但它还受到类模板参数的影响。因为它是类模板的成员,在类型推导时要结合类模板的参数。template <typename T> class MyClass { public: static void staticFunction(T t) { std::cout << "Static function type: " << typeid(t).name() << std::endl; } }; int main() { MyClass<int>::staticFunction(60); // 类模板参数为 int,结合传入实参,T 为 int MyClass<double>::staticFunction(70.5); // 类模板参数为 double,结合传入实参,T 为 double return 0; }
分析:在
MyClass<int>::staticFunction(60)
中,类模板参数为int
,传入int
类型实参,确定T
为int
;在MyClass<double>::staticFunction(70.5)
中,类模板参数为double
,传入double
类型实参,确定T
为double
。