2010-12-16 34 views
12

如果我定義一個類:如何獲取類名?

class Blah {}; 

哪有我:

std::string const className = /* What do I need to do here? */; 
assert(className == "Blah"); 

我不認爲typeid的()名稱()是一個好主意,因爲它是特定compiler implementation。 C++標準或Boost提供了什麼嗎?

注意:如果類是從Qt的QObject繼承的,我可以很容易地使用QMetaObject::className()來獲取類名。

回答

10

像這樣:

class Blah { static std::string const className() { return "Blah"; }}; 

std::string const name = Blah::className(); 
assert(name == "Blah"); 

或者這樣:

class Blah {}; 

template < typename T > struct name; 
template < > struct name<Blah> { static std::string value() { return "Blah"; }}; 

std::string const classname = name<Blah>::value(); 
assert(classname == "Blah"); 

票友:

#define DECLARE_NAMED_CLASS(Name) \ 
struct Name;\ 
template < > struct name<Name> { static std::string value() { return #Name; }};\ 
struct Name 

DECLARE_NAMED_CLASS(Blah) {}; 
std::string const className = name<Blah>::value(); 
... 

或者這樣:

class Blah : QObject { Q_OBJECT }; 

或者這樣:...... 或者這樣:...

+6

另一種解決方案將被TYPEID()+還原函數。否則,你如何處理命名空間等? – 2010-12-16 23:00:39

+2

typeid不保證是不可升級的。 – quetzalcoatl 2012-09-03 21:32:52

+0

第一種情況是唯一嚴重的情況。它易讀,易於維護和使用。第二個過度複雜化一個簡單的問題。也許你寧願使用REST api來調用web服務呢?第三個被認爲是壞習慣。當涉及到良好的設計時,預處理器是最糟糕的,也是最不應該使用的。對於預處理器,我能想到的唯一合理用例是編譯指示一次。 – nali 2017-12-05 22:25:55

1

我不認爲有任何非編譯器特定的解決方案,這種問題不涉及類聲明中的大量宏(實際上,如果我正確理解了QT文檔,您得到的字符串objectName實際上被分配了「by手「,我認爲用moc創建的代碼)。

另一方面,一般來說,檢查一個對象的類是不是你不希望你做字符串比較,而是做一個typeid比較。

assert(typeid(YourObject)==typeid(Blah)); 

但可能你應該更好地解釋你想要達到的目標。

3

測試一類通過看它的名字聽起來非常像一個Java風格的方法對我來說,在C++中,你應該警惕的嘗試應用相同圖案!更好的方法是使用像boost::type_traits這樣的東西,並且可能是is_same,並帶有真實的類名。

1

我認爲dynamic_cast可能是你在找什麼。 它不會給你類的名字,但它會以你希望斷言失敗的方式失敗,除非Blah的子類不會被捕獲。

1

我不認爲typeid()。name()是一個好主意,因爲它是編譯器 實現特定的。

是的,標準並不要求從實現中使用任何特定的命名,所以它甚至可以改變相同的編譯器。

C++標準或Boost提供了什麼嗎?

有沒有標準的設施,會返回類名稱在一些canonic形式。

1

的QObject->元對象()方法是有效的Qt的除了所述基於的QGraphicsItem類,不繼承QObject ...