C++ 模板以将类型作为参数而闻名,但它们也可以通过其他类型的数据进行参数化。例如,您可以将一个类模板化为一个整数,如下所示:
template <typename T, unsigned int N> class Array {
private:
T array[N];
public:
/* ... */
};
模板也可以通过指针参数化,只要指针满足某些标准(例如,它必须计算出可以在编译时确定的地址)。例如,这是完全合法的:
template <int* Pointer> class ThisIsLegal {
public:
void doSomething() {
*Pointer = 137;
}
};
在您的代码中,模板通过指向类成员的指针进行参数化。指向类成员的指针类似于指针,因为它间接引用了某个对象。但是,它不是指向一个对象,而是指向一个类中的一个字段。这个想法是,您可以取消引用相对于某个对象的指向类成员的指针,以从类中选择该字段。这是指向类成员的指针的简单示例:
struct MyStruct {
int x, y;
};
int main() {
MyStruct ms;
ms.x = 137;
ms.y = 42;
int MyStruct::* ptr; // Declare a pointer to a class member.
ptr = &MyStruct::x; // Now points to the field 'x'
ms.*ptr = 0; // Set the 'x' field of ms to be zero.
}
请注意,声明指向类成员的指针的语法是
Type ContainingClass::* pointerName;
所以在上面的代码中,int MyStruct::* ptr
意思是“指向类int
内部的指针MyStruct
。
在您发布的代码中,模板声明如下所示:
template <
class PropObject,
class PropType,
PropType PropObject::* Prop
>
class PropReader
让我们看看这意味着什么。将要读取其属性的前两个模板参数对象,以及PropType
该属性的类型。” 模板的最后一个参数是一个指向类成员的指针,名为Prop
,它指向 aPropObject
类型的字段PropType
。对于例如,你可以像这样实例化这个模板MyStruct
:
PropReader<MyStruct, int, &MyStruct::x> myPropReader;
现在,让我们看看其余代码的作用。此类模板的正文在此处转载:
void print(Object& o)
{
PropObject& po = static_cast<PropObject &>(o);
PropType& t = po.*Prop;
cout << t << "\n";
}
其中一些可以很容易地阅读。此函数的参数是对Object
命名的引用o
,最后一行打印出一些字段。这两行很棘手:
PropObject& po = static_cast<PropObject &>(o);
PropType& t = po.*Prop;
第一行是一个类型转换,它说“尝试将参数o
转换为 type 的引用PropObject
。我猜这个想法是Object
许多不同对象的一些基类。函数的参数只是一个普通的Object
, 并且此转换尝试将其转换为适当类型的东西(回想一下,PropObject
模板参数说明对象的类型是什么)。因为这使用static_cast
,如果未定义转换(例如,您尝试实例化模板超过int
or vector<string>
),代码将无法编译。否则,代码相信强制转换是安全的,然后获取PropObject
对参数所指的类型的引用。
最后,最后一行是
PropType& t = po.*Prop;
这使用了我之前提到的指向类成员的指针解引用语法来表示“选择Prop
(模板参数)指向的字段,然后存储对它的引用,命名为t
.
所以,简而言之,模板
- 询问您某些对象的类型。
- 询问您该对象中某个字段的类型。
- 要求您提供指向该对象中字段的指针。
- 提供
print
给定对象尝试打印该字段的函数。
哇!那很棘手!希望这可以帮助!