[英]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
從其模板類型轉換為實際的派生類型(如果它們不同)(未知)?
我不能修改Base
或Derived
,甚至不能修改任何調用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
。
如果不能同時更改Base或Derived或將析構函數設為虛擬,則可以將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.