给定一个对象初始化如下:
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
类本身。
答案 0 :(得分:4)
您需要模板化构造函数并存储类型删除的删除器。 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);
}
};
答案 1 :(得分:2)
如果您能够更改创建代码,则可以使用此方法:
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>);
答案 2 :(得分:0)
提示(因为这是作业):查找关键字virtual
。
答案 3 :(得分:0)
如果您无法同时更改 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;
}
答案 4 :(得分: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>();
编辑:有人早些时候发布了相同的解决方案。