代码之家  ›  专栏  ›  技术社区  ›  AK_

尝试计数派生类的实例时,类型\u id不起作用

  •  1
  • AK_  · 技术社区  · 14 年前

    我想计算我的类中所有派生程序的实例,我试着这样做:

    .h文件:

    #ifndef _Parant
    #define _Parant
    
    #include<map>
    
    class Parant
    {
    public:
        Parant();
        virtual ~Parant();
        static void PrintInstances();
    
    private:
        static void AddInstance(const char* typeName);
        static std::map<const char*, int> InstanceCounter;
    };
    
    #endif
    

    #include "Parant.h"
    #include <typeinfo>
    #include <iostream>
    
    using namespace std;
    
    Parant::Parant()
    {
        AddInstance(typeid(this).raw_name());
    }
    
    
    Parant::~Parant()
    {
    }
    
    
    std::map<const char*, int> Parant::InstanceCounter;
    
    void Parant::AddInstance(const char* typeName)
    {
        InstanceCounter[typeName]++;
    }
    
    
    void Parant::PrintInstances()
    {
        for(map<const char*,int>::iterator i = InstanceCounter.begin(); i != InstanceCounter.end(); i++)
        {
            cout << " typename: " << i -> first << " ;;" ;
            cout << " count: " << i -> second << endl ;
        }
    
    }
    

    我有两个如下所示的继承器(cpp包含空的实现):

    #pragma once
    #include "parant.h"
    class ChildA :
        public Parant
    {
    public:
        ChildA(void);
        virtual ~ChildA(void);
    };
    

    int main()
    {
        ChildA a;
        ChildB b;
        ChildA a1;
    
        Parant::PrintInstances();
    ....
    

    我得到的结果是:

     typename: .PAVParant@@ ;; count: 3
    

    为什么不起作用?

    我把它改成了

    AddInstance(typeid(*this).raw_name());
    

    当然还是不行,不过现在我明白为什么。。。我能让它工作吗?

    5 回复  |  直到 9 年前
        1
  •  5
  •   Johannes Schaub - litb    14 年前

    typeid(*this) 在一个构造函数中,只会产生构造函数的类(您已经拥有了它) typeid(this)

    另一个区别是,在构造期间调用的虚拟函数不会在派生类中结束,而是在构造期间进行调用的类中结束。

        2
  •  1
  •   James McNellis    14 年前

    Johannes解释了为什么这不起作用。

    作为一种可能的解决方法,您可以将指向派生类实例的指针传递给 Parent 使用初始化列表的构造函数:

    struct ChildA : Parent 
    {
        ChildA() : Parent(this) { }
    };
    

    起源 构造函数,如果你取消引用这个指针, typeid 起源 . 但是,你可以让 起源

    struct Parent
    {
        template <typename T>
        Parent(T* x)
        {
           AddInstance(typeid(T).raw_name());
        }
    
        // ...
    };
    

    将为每个派生类类型实例化此构造函数模板,并且 T 将是派生类的正确类型。

    this 显式指向基类构造函数的指针,但这是“解决”问题的一种方法。

        3
  •  0
  •   David    14 年前

    属于子类类型。但这就要求每个子类必须实现您的“接口”。

    C++不支持像java那样的反射,所以这不能以一般的方式轻松完成。

        4
  •  0
  •   bjskishore123    14 年前

    class Parent
    {
    public:
       Parent(const char* pClassName) //Gets called for every derived object with
       {                              //corresponding derived class name as parameter.
           AddInstance(pClassName);  //Instance count will be incremented here.
       }
    };
    
    class ChildA: public Parent
    {
    public:
        ChildA()
          : Parent("ChildA") //Pass the child class name to Parent.
        {
        }
    };
    class ChildB: public Parent
    {
    public:
        ChildB()
          : Parent("ChildB")
        {
        }
    };
    

    其余代码与您提供的代码相同。

        5
  •  0
  •   Chubsdad    14 年前

    这能满足你的需要吗?使用CRTP

    map<string, int> m;
    
    template<class T> struct Base{
        Base(){
            m[typeid(T).name()]++;    // potentially unsafe
        }
    };
    
    struct Derived : Base<Derived>{
    };
    
    struct AnotherDerived : Base<AnotherDerived>{
    };
    
    int main(){
        Derived d1, d2;
        AnotherDerived d11, d21;
    }