- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我是一名 C++ 程序员新手,但我认为我对 C++ 的了解已经足够了,直到今天我在工作中遇到了这样的代码,却无法理解它的实际工作原理。
class Object
{
};
template <
class PropObject,
class PropType,
PropType PropObject::* Prop
>
class PropReader
{
public:
void print(Object& o)
{
PropObject& po = static_cast<PropObject &>(o);
PropType& t = po.*Prop;
cout << t << "\n";
}
};
class Student : public Object
{
public:
int age;
int grade;
};
int _tmain(int argc, _TCHAR* argv[])
{
Student s;
s.age = 10;
s.grade = 5;
PropReader<Student, int, &Student::age> r;
PropReader<Student, int, &Student::grade> r2;
r.print(s);
r2.print(s);
}
我想我理解的程度很高。但是模板声明中的这个特殊的 PropType PropObject::* Prop
困扰着我。这是什么意思?我正在寻找 C++ 专家的解释。我想了解它,以便更好地使用它。不过看起来很有用。
最佳答案
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
的指向类成员的指针,它指向 PropObject
内的 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
转换为 PropObject
类型的引用。我猜这个想法是 Object
是很多不同的对象。函数的参数只是一个普通的 Object
,这个转换试图将它转换为适当类型的东西(回想一下 PropObject
是模板参数,说明对象的类型是什么)。因为这使用 static_cast
,如果未定义转换(例如,您尝试通过 int
或 vector<string>
实例化模板),代码将无法编译。否则,代码相信转换是安全的,然后获取类型为 PropObject
的对参数所指内容的引用。
最后,最后一行是
PropType& t = po.*Prop;
这使用了我之前提到的指向类成员的指针解引用语法来表示“选择 Prop
(模板参数)指向的字段,然后存储一个名为 t
的引用。
所以,简而言之,就是模板
print
给定对象的函数会尝试打印出该字段。哇!那很棘手!希望这会有所帮助!
关于c++ - Crazy C++ 模板 - 访问类的各个属性的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6784448/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!