[英]Alternative to virtual static functions in c++?
在頭文件.hpp中:
class Base{
public:
static /*Some Return Type*/ func(/*Some Datatype*/);
}
class Derived1 public Base{
public:
Derived1();
~Derived1();
}
class Derived1 public Base{
public:
Derived2();
~Derived2();
}
在cpp文件.cpp中:
/*Some Return Type*/ Derived1::func(/*Some Datatype*/){
}
/*Some Return Type*/ Derived2::func(/*Some Datatype*/){
}
這顯然是失敗的,因為無法在子類中覆蓋靜態方法。 但是如何獲得上述功能呢?
我必須這樣叫:
/*Some Return Type*/ result = Derived1::func(/*Some Datatype*/)
/*Some Return Type*/ result = Derived2::func(/*Some Datatype*/)
我知道,可以像下面這樣在基類中定義抽象方法,然后在Derived類中定義它們:
在頭文件.hpp中:
class Base{
public:
virtual /*Some Return Type*/ func(/*Some Datatype*/) const = 0;
}
但是問題是虛擬方法需要對象實例化,這不是我想要的。 我想在不創建對象的情況下調用該方法。 如果允許使用虛擬靜態方法,那么它們將達到目的。
我能想到的唯一選擇是在頭文件的所有Derived類中聲明函數func()
並將其從Base類中刪除。 有其他替代方法嗎? 這樣,聲明僅在基類中聲明一次,而所有派生類僅需定義它們,而無需重新聲明?
在沒有對象的情況下調用虛函數是矛盾的,因為分辨率取決於對象的類型。 在某些情況下,您可能需要根據對象的類型調用相同的函數,或者顯式地指定類而沒有對象。 通過使用兩個函數(一個靜態和一個虛擬)可以輕松地解決此問題。 (通常,虛擬的只會轉發到靜態的。)
一個簡單的例子(來自實際代碼):
#define DECLARE_CLASS_NAME(className) \
static char className() { return STRINGIZE(className); } \
virtual char* getClassName() { return className(); }
class Base
{
public:
DECLARE_CLASS_NAME(Base);
// ...
};
class Derived : public Base
{
public:
DECLARE_CLASS_NAME(Derived);
// ...
};
等等,在所有派生類中。 這用於獲取序列化的類型名稱,例如:
std::string typeName = pObj->getClassName();
並作為原始RTTI(大約20年前):
if ( pObj->getClassName() == Derived::className() ) ...
(我們建立了一個規則,獲得類名的唯一方法是使用以下函數之一。這有效地內部化了類名,並允許簡單的指針比較工作。在我們正在研究的系統上然后,這很重要。)
您可以這樣做有點hacky =)
//header file
template<class T>
struct base_t
{
static void do_smth();
};
struct derived1_t : base_t<derived1_t>
{
};
struct derived2_t : base_t<derived2_t>
{
};
//cpp file
void base_t<derived1_t>::do_smth() // `note base_t<derived1_t>::` instead of `derived1_t::`
{
std::cout << "aaa" << std::endl;
}
PS:很奇怪,您不想在派生類中聲明此函數,因為當您使用虛函數時,應在派生類中聲明它們
一種可能性是僅在派生類中定義它們:
struct Base
{
// nothing
};
struct Derived1 : public Base
{
static void func() { /*...*/ }
};
struct Derived2 : public Base
{
static void func() { /*...*/ }
};
這使您可以調用:
Derived1::foo();
Derived2::foo();
調用它的基本類型和期望編譯器要弄清楚你的意思是這亞型不能工作:
// How will the compiler know to choose
// between Derived1:: func or Derived2:: func ?
Base::func();
您可能希望查看CRTP或類型特征以找到替代方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.