[英]c++: how can I avoid the static_cast?
我有一個抽象基類和一個模板化派生類。 可以通過派生對象的先前實例(例如整數)來構造派生對象。 到目前為止,我們有
struct base {
/* ...pure virtual functions here... */
virtual ~base() = default;
/* NO DATA */
};
template <class D>
struct derived : base {
derived() = default;
derived(int x, const derived& previous) {
/* to construct I need access to previous.data_ */
}
/* ...overriden virtual functions here... */
~derived() = default;
D data_;
};
請注意,派生類的構造函數需要訪問previous
派生對象的data_
成員。 現在,我想創建一個函數,該函數將以整數和derived<D>
的先前實例為輸入,從而構造類型為derived<D>
的對象,並返回指向base
的指針。 問題在於,由於用戶將使用base
類指針,因此該函數應如下所示:
template <class D>
std::shared_ptr<base> getNext(int x, std::shared_ptr<base> current) {
return std::make_shared<derived<D>>(x, *current); /* ERROR */
}
您可能已經猜到了,這會產生一個編譯錯誤,指出沒有從base
到derived<D>
已知轉換。 我知道我可以使用的一件事是static_cast<derived<D>&>(*current)
因為基礎對象的類型將始終derived<D>
,但理想情況下,如果可能的話,我希望避免任何強制轉換。 任何想法如何克服這個問題>? 提前致謝!
您可以在基類中使用虛擬訪問器函數,該函數會告訴派生類是哪種類型。 然后,您可以安全地使用static cast
強制轉換來強制轉換基類。
class Animal {
virtual bool isDog() { return false; }
virtual bool isCat() { return false; }
};
class Dog : public Animal {
virtual bool isDog() { return true; }
};
class Cat : public Animal {
virtual bool isCat() { return true; }
};
然后,我可以像這樣安全地轉換基類:
Dog A;
Cat B;
Animal *unknown_animal = &A;
if (unknown_animal->isDog()) {
Dog *dog = static_cast<Dog*>(unknown_animal);
}
else if (unknown_animal->isCat()) {
Cat *cat = static_cast<Cat*>(unknown_animal);
}
如果您只需要知道派生的類型,而無需訪問它 ,則訪問器函數也很有用。
無論如何,您都不希望為此使用static_cast
。 您需要使用dynamic_pointer_cast
(並檢查結果以確保其可轉換為您的派生類型)。
如果您的界面具有填寫Data
對象所需的所有信息,則可以創建一個轉換構造函數,該構造函數將避免進行強制轉換:
template<typename T>
class MyDerived : public Base
{
public:
// other functions
MyDerived(std::shared_ptr<Base> p)
{
// initialize _data
}
private:
Data _data;
};
當您使用多態類時,發現自己需要轉換為派生類型,這通常是設計存在問題的線索。 畢竟,如果仍然需要使用派生類,為什么還要具有virtual
函數? 我並不是說這沒有例外-但我會說它們之間很少。
在這種情況下,您(認為自己)需要進行投射以克隆對象。 相反,我將在基類(此處稱為getNext
)上提供一個clone
方法。 將其設置為virtual
,在派生類中重寫它,然后調用它:
struct base {
public:
virtual std::shared_ptr<base> getNext(int x) = 0;
};
template <typename D>
struct derived : public base
{
public:
std::shared_ptr<base> getNext(int x)
{
std::shared_ptr <derived> clone = std::make_shared <derived<d>> (x, *this);
return std::static_pointer_cast <base> (clone);
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.