继承类型的指针之间的静态强制转换
static cast between pointers of inherited types
我正在尝试进行
static_cast<IntrusivePtr<B>>(IntrusivePtr<A>)
其中B公开来源于A。然而,这给出了错误
invalid conversion from A* to B*
有人能向我解释一下这里的问题吗?我可以通过做来绕过它
static_cast<B*>(IntrusivePtr<A>.get())
从理论上讲,这正是上述错误信息所说的不允许的。这是GCC 4.4.7
您要查找的概念称为类型协方差-您希望IntrusivePtr<T>
在T
上是协变的,这意味着如果D
是B
的子类型,则IntrusivePtr<D>
是IntrusivePtr<B>
的子类型。有些语言的类型系统支持这一点,C++不是其中之一。
在C++中,无论A
和B
是什么,IntrusivePtr<A>
和IntrusivePtr<B>
都是完全不相关的类型(除非它们是同一类型)。如果你想支持这种转换,你必须明确地支持它:
template <class T>
struct IntrusivePtr {
template <class U, class = std::enable_if_t<std::is_convertible<U*, T*>::value>>
IntrusivePtr(IntrusivePtr<U> const& rhs) { ... }
};
或者执行您正在执行的操作,并绕过IntrusivePtr
类模板。
回顾一下这个问题,IntrusivePtr
似乎更可能支持上述转换,但在这两种类型之间进行了隐式转换——这对派生到基有效,但对派生到基无效。但您始终可以显式地从基强制转换为派生。即:
struct B { };
struct D : B { };
B b;
D* d1 = &b; // error
D* d2 = static_cast<D*>(&b); // ok
IntrusivePtr<A>
和IntrusivePtr<B>
是完全不相关的类型。因此,不能在它们之间静态转换(除非IntrusivePtr
包含显式转换代码,或者A
和B
相同)。
注意,不能从基类静态地转换为派生类。
以下是如何更改IntrusivePtr的一种方法。
template <typename T>
struct IntrusivePtr {
IntrusivePtr(const IntrusivePtr& other) {
... // do the refcounting
ptr = other.ptr; // straight assignment, pointers are of the same type
}
template <typename Q,
typename = std::enable_if_t<std::is_convertible<Q*, T*>::value>>
IntrusivePtr(const IntrusivePtr<Q>& other) {
... // do the refcounting
ptr = other.ptr; // straight assignment, pointers are compatible
}
// this can only be used in explicit conversions
template <typename Q,
typename = std::enable_if_t<std::is_convertible<T*, Q*>::value>>
// must add bogus default parameter, or the compiler will complain
explicit IntrusivePtr(const IntrusivePtr<Q>& other, int=0) {
... // do the refcounting
ptr = static_cast<T*>(other.ptr); // explicit downcast, trust the programmer
}
... // other methods
T* ptr;
};
检查:
struct A {};
struct B : A {};
IntrusivePtr<A> a;
IntrusivePtr<B> b;
a = a; // ok, straight copy
a = b; // ok, implicit upcast
b = static_cast<IntrusivePtr<B>>(a); // ok, explicit downcast
b = a; // error, implicit conversion is not allowed
但是,如果IntrusivePtr离boost::intrusive_ptr不远,它应该具有类似于boost::intrusive_ptr::static_pointer_cast
的功能。可能应该使用它,尤其是对于不支持C++11的编译器。
相关文章:
- enable_if转换构造函数(静态强制转换,is_base_of)
- 使用转换器提升 Python 问题 - 静态链接
- 不要使用静态强制转换进行算术转换(cpp-core-guidelines)
- C++实用程序::转换在静态链接库中不起作用
- 静态成员变量不会由 gettext 转换
- C++ 将静态方法转换为简单方法
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 指向 POD 类型的指针之间的静态转换与重新解释转换
- 静态强制转换内的表达式
- 我需要静态转换我的数字模板值吗
- 使用静态转换,因为动态转换失败.不好的做法?
- 静态转换父级到子级C++
- 是否应该避免这种从 int 到双精度的静态转换?
- 如何在C++中正确静态转换矢量
- 枚举静态转换为布尔,编译器发出性能警告
- 静态转换接口类到内部引擎实现
- 整型常量到const char*的静态转换
- 如何在无符号int和int之间安全地静态转换
- 将接口静态转换为派生类