不能动态强制转换为ptr
Cannot dynamic cast to ptr
我试图实现非常基本的类类似于boost::any,但有一个问题,我正面临着,我不能越过这个。问题是使用dynamic_cast将指针转换为另一个指针,错误说:
cannot dynamic_cast 'input.Any::m_targetPtr' (of type 'class Any::StorageInterface*') to type 'int*' (target is not pointer or reference to class)
类的来源如下:
class Any{
public:
template <typename T>
Any(T input): m_targetPtr(new StorageImpl<T>(input)){}
~Any(){delete m_targetPtr;}
class StorageInterface{
public:
virtual ~StorageInterface(){}
};
template<typename T>
T* cast(Any& input){
return dynamic_cast<T*>(input.m_targetPtr); //here comes the trouble
}
template <typename T>
class StorageImpl : public StorageInterface{
public:
StorageImpl(T& input): m_target(&input){}
T* m_target;
};
StorageInterface* m_targetPtr;
};
我想这样执行:
int i=150;
Any asdf(i);
cout<< (asdf.cast<int>(asdf)) << endl;
我的理解是。我有一个int
变量和cast
模板,我传递指针到这个int和模板中的T
是int,因此在转换源中,我们有int
作为推导参数int*
作为返回值,我用StorageInterface*
类型的参数m_target
执行dynamic_cast<int*>
。为什么我得到一个错误,我的目标不是一个指针?
我在以下代码中看到以下问题:
template<typename T>
T* cast(Any input){
return dynamic_cast<T*>(input.m_targetPtr); //here comes the trouble
}
您需要强制转换为
StorageImpl<T>*
,而不是T*
StorageImpl
不公开m_target
成员
公开m_target
成员,将其设置为public
或提供返回值的函数。
修改cast
函数为:
template<typename T>
T* cast(Any input){
return dynamic_cast<StorageImpl<T>*>(input.m_targetPtr)->m_target;
}
改进建议:
在cast
中不需要input
参数。它可以是:
template<typename T>
T* cast(){
return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target;
}
然后,您的调用也可以简化为:
cout<< (asdf.cast<int>()) << endl;
// ^^^ No need to use asdf again in the call.
进一步改进建议
代码中的StorageImpl
存储了一个指向对象的指针,这个指针很容易失效。我建议存储一个对象。这样,Any::cast()
就可以返回一个引用,而不是一个指针。
class Any {
public:
template <typename T>
Any(T input): m_targetPtr(new StorageImpl<T>(input)){}
~Any(){delete m_targetPtr;}
class StorageInterface {
public:
virtual ~StorageInterface(){}
};
template<typename T>
T const& cast() const {
return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target;
}
template<typename T>
T& cast() {
return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target;
}
template <typename T>
class StorageImpl : public StorageInterface {
public:
StorageImpl(T const& input): m_target(input){}
T m_target;
};
StorageInterface* m_targetPtr;
};
问题是,如果X
不属于与T
相同的类层次结构,dynamic_cast<T>(X)
无法将类型X转换为类型T
。动态强制转换意味着多态性,例如,将Animal*
向下强制转换为Dog*
,其中class Dog
继承自class Animal
, class Animal
包含虚函数。问题是int
不是类类型,所以dynamic_cast
可以很早就得出int
和StorageInterface
不共享类层次结构的结论。
错误信息不是说你的目标不是指针,而是说你的目标不是指向类对象的指针(也不是对类对象的引用)。
R Sahu指出,您打算转换为StorageImpl<T>*
,这更有意义。
dynamic_cast<T>
用于将一个多态结构体的指针转换为同一层次结构中的另一个多态结构体。多态结构是具有至少一个虚函数或虚继承的结构。显然,int*不是结构体,也不是多态的。
你可能想用这个来代替:
template<typename T>
T* cast(Any input){
return dynamic_cast<StorageImpl<T>*>(input.m_targetPtr)->m_target; // better?
}
为什么要发送对象的副本给自身呢?如果将函数限制为实例本身,则更不容易出错:
template<typename T>
T* cast(){
return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target; // even better
}
你现在可以这样使用:
asdf.cast<int>();
最后,为了使您的代码更干净,更不容易出错,可以做最后一件事。你看到潜在的未定义行为了吗?您的代码中有双重删除:
template<typename T>
T* cast(Any input){
return dynamic_cast<T*>(input.m_targetPtr); //here comes the trouble
// input is deleted here, so asdf will have a dangling pointer and double delete the m_targetPtr!
}
在你的构造函数中,你保存了一个临时的地址:
// input is a reference to a variable from the 'Any' class constructor, it will be deleted
StorageImpl(T& input): m_target(&input){}
通过value(和move)传递可以解决这个问题。
任何使用这个类的代码都可能出现这些错误。使用std::unique_ptr
和值语义可以达到这个目的:
struct Any {
template <typename T>
Any(T input): m_targetPtr(new StorageImpl<T>(std::move(input))){}
/* ~Any(){delete m_targetPtr;} */
// no destructor needed here, you can safely remove the line above.
// you could implement a copy constructor which clone the m_targetPtr.
class StorageInterface{
public:
virtual ~StorageInterface(){}
};
template<typename T>
T& cast(){
return dynamic_cast<StorageImpl<T>*>(m_targetPtr.get())->m_target;
}
template <typename T>
class StorageImpl : public StorageInterface{
public:
StorageImpl(T input): m_target(std::move(input)){}
T m_target;
};
private:
std::unique_ptr<StorageInterface> m_targetPtr;
};
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 为什么我不能在不进行任何转换的情况下将浮点数放入任何类型的 ptr 中?
- 从const ptr*转换为ptr*时出现问题
- C++ 类型转换基础 PTR 到派生 PTR 保存在引用类中
- 将 lamba 隐式转换为函数 ptr 以创建类
- 为什么非常量ptr不能隐式地将ptr转换为常量作为模板中的参数
- C++双PTR到长PTR转换
- 无法将 Uchar PTR 转换为 OpenCVsharp
- 不能动态强制转换为ptr
- 函数PTR转换为带模板参数的函数
- 将派生类的ptr类型转换为ptr类型
- 将输入字符串转换为字符* <错误 Ptr>