2017-07-28 90 views
1

我做了一個基類對象來跟蹤一些對象的實例。我想在一個文件中記錄此像這樣:如何跟蹤多個對象實例?

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

有沒有其他的辦法來記錄哪個對象被分配和釋放?

+0

名稱和符號僅在源中可用。一旦[*翻譯單元*](https://en.wikipedia.org/wiki/Translation_unit_(編程))已被編譯成目標文件並鏈接到可執行文件中,它基本上會丟失所有符號。 C++沒有標準[* introspection *](https://en.wikipedia.org/wiki/Introspection_(computer_science))或[* reflection *](https://en.wikipedia.org/wiki/Reflection_(computer_programming) )設施。 –

+1

您可以在每個返回一個字符串並在構造函數中調用它的類中實現一個'typename()'方法。 – idmean

+0

@idmean爲了完整起見,這樣一種方法可能(需要)是'靜態'。 – TripeHound

回答

1

你沒」的想法這將是有趣t指定你將如何使用這個CountedObj。我想這:

​​

如果從Foo進一步推導,那麼你的計數器已經無法富區分,及其派生類,所以我想你想打印「富」作爲名稱的所有派生類。如果你想區分這些類,那麼需要一個不同的解決方案(如果是這種情況,我會刪除這個答案)。

(或者,也許你可以從CountedObj再次獲得:class FooDerived: public Foo, public CountedObj<FooDerived> { };,但這樣一來,FooDerived會算既是FooDerivedFoo

所以,你可以使用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"; 
     } 
}; 
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,我用了一個包含每個類的一個instanciation *的向量(我們只需要一個訪問不同的類變量)。

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這是打算在我提供的解決方案