簡體   English   中英

C ++:如何避免static_cast?

[英]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 */
}

您可能已經猜到了,這會產生一個編譯錯誤,指出沒有從basederived<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM