在构造过程中应用type_id运算符

To apply type_id operator during the construction

本文关键字:id 运算符 type 应用 过程中      更新时间:2023-10-16

代码:

#include <iostream>
#include <typeinfo>
#include <cassert>
using std::cout;
using std::endl;
long unsigned int hash_in_constructor;
struct A
{
    virtual void foo()
    {
        cout << "A" << endl;
    }
    A()
    { 
        hash_in_constructor = typeid(this).hash_code();
    }
};

int main()
{
    cout << hash_in_constructor << endl;
    cout << typeid(A).hash_code();
}

演示

我预计hash_in_constructor等于typeid(A).hash_code(),因为12.7/5:

在构造函数中使用typeid时(包括mem初始值设定项或非静态数据成员的大括号或相等初始值设定项)或析构函数,或用于从构造函数或析构函数,如果typeid的操作数引用正在构建或销毁的对象,typeid会生成std::type_info对象,表示构造函数或析构函数的

但事实并非如此。为什么?

有两个明显的问题:

  1. 仅当执行A::A时、当构造A的实例时才设置hash_in_constructor

    您在构造A的实例之前阅读了它,所以它还没有被设置(只是被静态初始化为零)。

  2. 你在比较typeid(A)typeid(A*),它们是不同的。请记住,this指针就是一个指针。

检查此版本代码的输出:

#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl;
long unsigned int hash_in_constructor;
struct A {
    virtual void foo() {
        cout << "A" << endl;
    }
    A() { 
        hash_in_constructor = typeid(this).hash_code();
    }
};

int main() {
    cout << "static init = " << hash_in_constructor << endl;
    A a;
    a.foo();
    cout << "after ctor = " << hash_in_constructor << endl;
    cout << "typeid(&a) = " << typeid(&a).name() << " : " << typeid(&a).hash_code() << endl;
    cout << "typeid(a) = " << typeid(a).name() << " : " << typeid(a).hash_code() << endl;
    cout << "typeid(A) = " << typeid(A).name() << " : " << typeid(A).hash_code() << endl;
}

输出:

g++ -std=c++1y -Wall -Wextra -pedantic -pthread main.cpp -lcxxrt -ldl && ./a.out
static init = 0
A
after ctor = 15127845526165118748
typeid(&a) = P1A : 15127845526165118748
typeid(a) = 1A : 1295143305205299629
typeid(A) = 1A : 1295143305205299629

您必须使用typeid(*this)而不是typeid(this),否则您将获得A*的类型信息,这当然与A不同。