模板参数扩展
我们前面提到:我们不可以将自定义类类型作为非类型模板参数,但是我们想想“可不可以把类的静态/非静态成员部分作为非类型模板参数呢”?
① 将类类型的非静态成员作为非类型模板参数
#include <iostream>
using namespace std;
class Student
{
public:
int age;
public:
Student() :age(0) {};
void ShowInf();
};
void Student::ShowInf()
{
cout << this->age << endl;
}
template <typename T,typename F>
void Test(T& obj, F Func)
{
(obj.*Func)();
}
int main()
{
Student obj;
Test(obj, &Student::ShowInf);
}
注意:普通成员函数不能离开类对象而存在,因此我们必须在函数中传入一个类对象,让这个类对象去调用类的普通成员函数。
② 将类类型的静态成员函数作为模板的非类型参数
#include <iostream>
using namespace std;
class Student
{
public:
static int age;
public:
static void ShowInf();
};
int Student::age = 0;
void Student::ShowInf()
{
cout << Student::age << endl;
}
template <typename F>
void Test(F Func)
{
Func();
}
int main()
{
Test(&Student::ShowInf);
}
注意:由于静态成员函数不需要依赖于类对象,因此我们可以把静态成员函数当作普通函数来看待。
③ 将类的公有成员数据作为非类型模板参数
#include <iostream>
using namespace std;
class Student
{
public:
int age;
public:
Student() :age(0) {};
};
template <int Student::*obj>
void ShowInf()
{
cout << obj << endl;
}
int main()
{
ShowInf<&Student::age>(); // 输出1而非我们想看到的0
}
注意:
为何输出结果不同,因为“成员指针”并不是一个确定的地址而是相对于类的this指针的偏移量,详见:
④ 将类的静态成员数据作为模板的非类型参数
#include <iostream>
using namespace std;
class Student
{
public:
static int age;
};
int Student::age = 0;
template <int& obj> // 切记要加&引用
void ShowInf()
{
cout << obj << endl;
}
int main()
{
ShowInf<Student::age>();
}
注意:切记要加&引用!
我们只能通过引用/指针来访问静态变量,我们使用指针在访问一次静态成员变量:
#include <iostream>
using namespace std;
class Student
{
public:
static int age;
};
int Student::age = 0;
template <int* obj> // 参数为指针
void ShowInf()
{
cout << *obj << endl;
}
int main()
{
ShowInf<&Student::age>();
}
关于static静态成员的详细解析: