如何跟踪多个对象实例?

时间:2017-07-28 07:56:23

标签: c++

我创建了一个基类对象来跟踪某些对象的实例。我想在这样的文件中记录它:

Object Name: Number of instances

这是我的基类:

template <class T>
class CountedObj
{
public:
   CountedObj()
   {
        // write name of derived class and counter to log
   }

   CountedObj(const CountedObj& obj)
   {
       // write name of derived class and counter to log
   }

   ~CountedObj() 
   {
       // write name of derived class and counter to log
   }
private:
   int counter;
   mylogger log;
};

我的问题是我要打印将继承自CountedObj的类的名称,但我不能在构造函数中使用typeid

是否有任何替代方法可以记录分配和取消分配哪个对象?

2 个答案:

答案 0 :(得分:1)

您没有指定如何使用此CountedObj。我假设这个:

class Foo: public CountedObj<Foo> {
};

如果从Foo进一步派生,那么你的计数器已经无法区分Foo及其派生类,所以我想你要打印“Foo”作为所有派生类的名称。如果你想区分这些类,那么需要一个不同的解决方案(如果是这样的话我会删除这个答案)。

(或者您可以从CountedObj class FooDerived: public Foo, public CountedObj<FooDerived> { };再次获得,但这样,FooDerived将被计为FooDerivedFoo)< / p>

所以,可以以这种方式使用typeid:

template <typename T>
class CountedObj {
    public:
        CountedObj() {
            counter++;
            printf("%s: %d\n", typeid(T).name(), counter);
        }
    private:
        static int counter; // static is needed
};

如果您不喜欢typeid().name()的输出,那么您可以在Foo中添加静态名称查询功能:

template <typename T>
class CountedObj {
    public:
        CountedObj() {
            counter++;
            printf("%s: %d\n", T::name(), counter);
        }

        ...
};

class Foo: public CountedObj<Foo> {
    public:
        static const char *name() {
            return "Foo";
        }
};

答案 1 :(得分:0)

编辑:这是一个更好更清洁的版本

解决方案是在 CountedObj 中使用unordered_map。这是类名称和实例数之间的关联映射。

然后对于每个类,存储CountedObj并增加unordered_map中的实例数。

#include <stdio.h>
#include <iostream>
#include <string>
#include <unordered_map>

class CountedObj
{
public:
   void increase_instance(const std::string& s)
   {
       if (instances.find(s) == instances.end())
           instances[s] = 1;
       else
           instances[s] += 1;
   }

    void pretty_print()
    {
        for(auto& n = instances.begin(); n != instances.end(); ++n)
            std::cout << "Name of the class " << n->first << " : instances =>" << n->second << std::endl;
    }
private:
    std::unordered_map<std::string, unsigned int> instances;
};

class A
{
    public:
        A(CountedObj& o)
            : name("A"),
              obj(o)
        {
            o.increase_instance(name);
        }
        const std::string& name;
    private:
        CountedObj& obj;
};

class B
{
    public:
        B(CountedObj& o)
            : name("B"),
              obj(o)
        {
            o.increase_instance(name);
        }
        const std::string& name;
    private:
        CountedObj& obj;
};


int main()
{
    CountedObj c;
    A a(c), aa(c), aaa(c);
    B b(c), bb(c);
    c.pretty_print();
    return 0;
}

节目输出

Name of the class A : instances =>3
Name of the class B : instances =>2

如果您不想在每个班级中存储CounterObj,您可以将CounterObj类定义为Singleton

======

  

我创建了一个基类对象来跟踪某些对象的实例。

您是否认为您要跟踪的对象是相关的? (例如,基类A有几个孩子,如B和C)。如果你想跟踪不同的实例,最好有一个唯一的类型来存储对象(比如在A的向量中)。

要跟踪每个类的实例数,需要为每个可跟踪类存储一个静态int(类变量)。

在每个构造函数中,将此变量增加1。

#include <iostream>
#include <vector>
#include <string>

class A
{
    public:
        A(const std::string& n) : name("A")
        {
            instance_num += 1;
            name = n;
        }
        std::string toString()
        {
            return name;
        }
        virtual int instance_num_get()
        {
            return instance_num;
        }
        static int instance_num;
    protected:
        std::string name;
};


class B : public A
{
    public:
        B() 
          : A("B")
        {
            instance_num += 1; 
        }
        int instance_num_get()
        {
            return instance_num;
        }
        static int instance_num;
};


class C : public A
{
    public:
        C()
          : A("C")
        {
            instance_num += 1; 
        }
        int instance_num_get()
        {
            return instance_num;
        }
        static int instance_num;
};

对于 CountedObj ,我使用了一个A *向量,其中包含每个类的一个实例(我们只需要一个来访问不同的类变量)。

template<typename T>
class CountedObj
{
    public:
        CountedObj(std::vector<T*>& v)
          : obj_list(v)
        {
        }

        void pretty_print()
        {
            for (auto elt = obj_list.begin(); elt != obj_list.end(); ++elt)
                std::cout << (*elt)->toString() << ": " << (*elt)->instance_num_get() << std::endl;
        }

    private:
       std::vector<T*> obj_list;
};

使用 pretty_print 方法,我们显示类的名称和实例化的数量。

我们初始化类变量。这是一个有效的例子:

int A::instance_num = 0;
int B::instance_num = 0;
int C::instance_num = 0;

int main(void)
{
    A a("A");
    B b;
    C c;
    std::vector<A*> vec;
    vec.push_back(&a);
    vec.push_back(&b);
    vec.push_back(&c);
    CountedObj<A> count(vec);
    count.pretty_print();
    return 0;
}

将给出

Output:
    A: 3
    B: 1
    C: 1

我认为使用Observer design pattern会很有趣,这是我提供的解决方案中的想法