我可能只是忽略了某些東西或愚蠢,在這種情況下我很抱歉,但我真的不確定如何(如果可能的話)訪問虛擬成員函式。實際上,虛擬部分是關于可能的解決方案的第二個問題,我將在后面描述。這是一些總結我的問題的示例代碼:
class BaseClass
{
public:
virtual std::string ClassName()
{
return "BaseClass";
}
};
class DerivedClass : public BaseClass
{
public:
std::string ClassName()
{
return "DerivedClass";
}
};
template<class cT>
void StatusPrint(const std::string& message)
{
return cT.ClassName(); // Here's where my issue arises.
}
所以,我想,以取代cT.與ct::然而,而導致對自己的編譯器的問題,它也試圖訪問BaseClass的虛函式,但我想訪問DerivedClass重寫的功能。
我正在嘗試做的事情可能是這樣嗎?
uj5u.com熱心網友回復:
對不起,如果我看起來很粗魯,但你不能從void函式中回傳任何東西。顯然,我們在這里沒有完整的故事。
你真的想要一個編譯時解決方案嗎?
查看您的代碼,似乎className()根本沒有使用物件的狀態。所以你可以做到static(而不是virtual)。然后問題將通過以下方式解決:
template<class cT>
std::string StatusPrint(const std::string& message) // returns string, not void
{
return cT::ClassName(); // :: if class name is static.
}
由于模板無法從其引數派生型別,因此您需要提供它,使類的選擇完全在compile-time:
cout<< StatusPrint<DerivedClass>("test"s)<<endl;
當您有一些實用程式類并且想要在編譯時配置要使用哪一個時,就會使用這種做法。
您想要動態解決方案嗎?
如果您想在運行時獲得動態解決方案,則需要使用一些物件,因為virtual需要一個在運行時知道其動態型別的物件。
然后取決于背景關系。一種解決方案是使用cT引數,具有引數推導的優點:
template<class cT>
std::string StatusPrint ( cT object, const std::string& message)
{
return object.ClassName(); // Here's where my issue arises.
}
然后你會呼叫它:
DerivedClass test;
...
cout<< StatusPrint(test, "test"s)<<endl;
在線演示
但是當然,它也可以使用一些全域物件來代替(但是模板的意義要小得多),或者更好的是,如果您將 StatusPrint() 重構為此類的成員函式,則可以使用模板類中的物件。
uj5u.com熱心網友回復:
我不確定你到底想做什么,但看看這是否更像它:
std::string StatusPrint(BaseClass *instance) {
return instance->ClassName();
}
模板引數用于型別,虛擬繼承需要指標。
DerivedClass derived;
std::cout << StatusPrint(&derived) << std::endl; // note the &
uj5u.com熱心網友回復:
cT是一個型別,而不是一個物件。您只能在物件實體上呼叫函式(除非它們是靜態函式,但這不是您要在此處執行的操作)。您需要傳入要列印的物件的實體。例如
template<class T>
std::string StatusPrint(const T& obj, const std::string& message)
{
return obj.ClassName();
}
習慣上用大寫來命名模板型別以避免這種混淆。
我不得不承認編譯器錯誤令人困惑,但它確實給你一個提示,即cT. 它是說,之前發生.的不是它所期望的。
使用 GCC 9:
error: expected primary-expression before '.' token
24 | return cT.ClassName();
| ^
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/406383.html
標籤:
