我正试图从一个通用转换为另一个,比如说:
myClass<MoreAbstract> anItem = myclass<DerivateFromMoreAbstract> anotherObject;
或做类似
的事情aFunction(anotherObject); // myclass<DerivateFromMoreAbstract> anotherObject
其中aFunction签名是
aFunction(myClass<MoreAbstract> item);
实际上,myClass实际上是我在网上找到的shared_ptr的简化实现。我想知道是否有任何方式我可以实际从一种指针类型切换到另一种被封装的类型。
有没有办法做这样的演员?如果是这样,那么正确的做法是什么?
如果它对任何人有帮助,VC ++会给我这个错误:
Error 1 error C2440: 'type cast' : cannot convert from 'myClass<T>' to 'myClass<T>'
答案 0 :(得分:11)
您不能进行静态转换,因为它们是不兼容的类型。您有时可以创建一个操作符来强制改变类型
#include <iostream>
class A { };
class B : public A { };
template<typename T>
struct holder {
T* value;
holder ( T*value ) : value ( value ) { }
template < typename U > // class T : public U
operator holder<U> () const
{
return holder<U>( value );
}
};
int main ()
{
using namespace std;
B b;
holder<B> hb ( &b );
holder<A> ha = hb;
cout << boolalpha;
cout << ( hb.value == ha.value ) << endl;
return 0;
}
这是否是一个有意义的操作,而是取决于模板类的语义 - 如果aFunction
可以将任何内容放入处理程序中,则不希望更具体的对象发生变异。因此,您可以使用强制运算符或模板复制构造函数和赋值以某种方式进行复制。 (强制代码较少,但如果不使用引用参数,可能会导致创建更多对象)
答案 1 :(得分:6)
类型不是以这种方式默认可转换的(因为您可能不希望对象这样做)。一般来说,您可以采取两种方法:
实现一个显式的强制转换函数,它可能对运行时强制转换很有用,比如boost's shared_ptr dynamic_pointer_cast。你最终会得到类似的东西:
template <typename To, typename From>
myclass<To> myclass_cast(const myclass<From>&)
{ /* do a runtime cast, possibly with exceptions */ }
第二种方法是转换构造函数,如果它们是可转换的,则在编译时它是可判定的。例如,如果所有类都可以从Derived上的模板转换为基于模板化,那么这里的构造函数只有在为真时才能生效(使用enable_if和boost :: type_traits):
template <typename To>
class myclass {
//converting constructor
template <typename From>
myclass(const myclass<From>&,
typename enable_if<boost::type_traits::is_base_of<To, From> >::type* dummy = 0)
{ }
};
答案 2 :(得分:3)
抱歉,这是不可能的。 (好吧,除非你做了讨厌的reinterpret_cast
黑客攻击,但是你不想这样做 - 最终的结果不会很好。)
T<Base>
和T<Derived>
无关。编译器不能假设 - 记住T完全可能是Derived专门用于完全不同的东西。
答案 3 :(得分:1)
c ++中的模板以及c ++ .net中的泛型不是协变的。
检查this问题,可能会让您了解解决方法。