簡體   English   中英

從基類到未知派生類的轉換

[英]Casting from base class to unknown derived class

給定一個像這樣初始化的對象:

Base* a = new Derived();
Container<Base> c(a);

哪里

class Base {
  ...
  protected:
    ~Base();
}

class Derived : public Base {...};

template <typename T>
class Container {
  private:
    T* object;

  public:
    Container(T* o) : object(o) {}
    void deleteObject() {
      delete object;  // Object must be casted to (unknown) derived type to call destructor.
    }
};

顯然,這與實際代碼相比非常簡化,但是問題是如何將object從其模板類型轉換為實際的派生類型(如果它們不同)(未知)?

我不能修改BaseDerived ,甚至不能修改任何調用Container的代碼,只能修改Container類本身。

您需要對構造函數進行模板化並存儲類型擦除的刪除器。 這就是shared_ptr工作方式。

template <typename T>
class Container {
  private:
    T* object;
    std::function<void(T*)> deleter;
  public:
    template<typename U> Container(U* o) : object(o) {
        deleter = [](T* ptr) { delete static_cast<U*>(ptr); };
    }
    void deleteObject() {
        deleter(object);
    }
};

如果您能夠更改創建代碼,則可以避免以下問題:

template<class T>
void deleter(void* p){
  delete static_cast<T*>(p);
}

template<class T>
class Container{
private:
  T* obj;
  typedef void (*deleter_func)(void*);
  deleter_func obj_deleter;

public:
  Container(T* o, deleter_func df)
    : obj(o), obj_deleter(df) {}
  void deleteObject(){ obj_deleter(obj); }
};

並在調用代碼中:

Base* a = new Derived();
Container<Base> c(a, &deleter<Derived>);

提示 (因為這是家庭作業):查找關鍵字virtual

如果不能同時更改BaseDerived或將析構函數設為虛擬,則可以將deleteObject設置為模板函數

template <typename T>
class Container {
  private:
    T* object;

  public:
    Container(T* o) : object(o) {}


    template <typename U>
    void deleteObject() {
      U* c = static_cast<U*>(object);
      delete c;
    }
};


int main(void)
{
    Base* a = new Derived();
    Container<Base> *b = new Container<Base>(a);


    b->deleteObject<Derived>();
        return 0;
}

編輯:我不知道你也不能修改Container簽名...

如果可以修改deleteObject

template <typename T>
class Container {
  private:
    T* object;

  public:
    Container(T* o) : object(o) {}
    template< typename PDerived >
    void deleteObject() {
      delete static_cast< PDerived* >( object ); 
    }
};

Base* a = new Derived();
Container<Base> c(a);

c.deleteObject<Derived>();

編輯:有人早些時候發布了相同的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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