我需要跟蹤爲特定類創建的所有對象,並且需要使用標識符字符串來訪問它們。以下代碼幾乎完全符合我的需求。 NamedObject類具有靜態成員m_object_by_name,它將名稱(字符串)映射到對象,構造函數將每個創建的對象添加到地圖,析構函數從地圖中刪除已刪除的對象。C++:跟蹤所有現有的對象
#include <map>
#include <string>
#include <iostream>
using namespace std;
class NamedObject
{
public:
static NamedObject *object_by_name(const string &name) {
return m_object_by_name[name];
}
NamedObject(const string &name) : m_name(name) {
m_object_by_name[m_name] = this;
}
~NamedObject() {
m_object_by_name.erase(this->m_name);
}
const string &name() const{
return m_name;
}
private:
string m_name;
static map<string, NamedObject *> m_object_by_name;
};
map<string, NamedObject *> NamedObject::m_object_by_name;
int main()
{
new NamedObject("name1");
new NamedObject("name2");
NamedObject *obj1 = NamedObject::object_by_name("name1");
NamedObject *obj2 = NamedObject::object_by_name("name2");
cout << obj1->name() << endl;
cout << obj2->name() << endl;
}
現在我有幾個類的對象需要通過他們的名字來訪問。繼承形式上面的NamedObject類當然有一個問題,即所有這些類將共享它們的名稱(例如,我不能擁有兩個不同類的對象,但名稱相同),因爲它們共享地圖m_objects_by_name。而且,當使用object_by_name()方法訪問對象時,我總是必須從NamedObject投射到實際的類。
此問題我現在使用的解決方案可以在下面的代碼中看到。然而,我對這個解決方案並不滿意(見下面的評論)。模板類NamedObjectStore現在負責存儲類T的所有對象。此外,還有一個基類處理具有真正使用的名稱和派生類的屬性。派生類有一個靜態NamedObjectStore對象,它在創建時添加對象,並在刪除時將其刪除。
#include <map>
#include <string>
#include <iostream>
using namespace std;
template <class T>
class NamedObjectStore
{
public:
void add_object(T *obj) {
m_object_by_name[obj->name()] = obj;
}
void rem_object(T *obj) {
m_object_by_name.erase(obj->name());
}
T *object_by_name(const string &name) {
return m_object_by_name[name];
}
private:
map<string, T *> m_object_by_name;
};
class BaseNamedObject
{
public:
BaseNamedObject(const string &name) : m_name(name) {
}
const string &name() const {
return m_name;
}
private:
string m_name;
};
class DerivedNamedObject : public BaseNamedObject
{
public:
static NamedObjectStore<DerivedNamedObject> store;
DerivedNamedObject(const string &name) : BaseNamedObject(name) {
store.add_object(this);
}
~DerivedNamedObject() {
store.rem_object(this);
}
};
NamedObjectStore<DerivedNamedObject> DerivedNamedObject::store;
int main()
{
new DerivedNamedObject("name1");
new DerivedNamedObject("name2");
DerivedNamedObject *obj1 = DerivedNamedObject::store.object_by_name("name1");
DerivedNamedObject *obj2 = DerivedNamedObject::store.object_by_name("name2");
cout << obj1->name() << endl;
cout << obj2->name() << endl;
}
從積極的一面,是什麼使對象的命名對象的實現(即名稱() - 函數)在基類BaseNamedObject完成。存儲所有對象的結構的實現位於NamedObjectStore類中,並隱藏在其方法後面。這使我可以根據需要輕鬆更改這兩個實現,而無需觸及所有派生類。
在消極的一面,我仍然需要反覆輸入相同的東西。更確切地說,對於每個派生類(比如DerivedNamedObject),我必須聲明並定義靜態成員存儲,我必須在構造函數中將商店對象添加到商店中,並在析構函數中將其從商店中移除。
因此,我的問題是:是否有更好的方法來解決這個問題?或者我只需要在每個派生類中使用這四行代碼?
希望能對一些鼓舞人心的建議:-)
托馬斯
http://codereview.stackexchange.com/可能是一個更好的地方。 – crashmstr
聽起來像http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern就足夠了 – Chad
如果你要從NamedObject繼承,應該有一個虛擬析構函數。 –