[英]C2440 static_cast cannot convert from base class to derived class
I am attempting to understand why casting from a base class to an derived class using pointers compiles fine, but casting using non-pointer object produces the error C2440. 我试图理解为什么使用指针从基类强制转换为派生类的编译效果很好,但是使用非指针对象进行强制转换会产生错误C2440。
Below I have a base class ThreadedMessage
that is inherited by class GPSMessage
. 下面有一个基类
ThreadedMessage
,它由类GPSMessage
继承。
struct ThreadedMessage
{
ThreadedMessage()
: m_Type(0), m_ID(0)
{ }
ThreadedMessage(uint Type, uint ID = 0) :
m_Type(Type), m_ID(ID)
{ }
uint m_Type;
uint m_ID;
};
struct GPSMessage : public ThreadedMessage
{
GPSMessage()
: ThreadedMessage()
{ }
GPSMessage(double lat, double lon)
: ThreadedMessage(1), m_lat(lat), m_lon(lon)
{ }
double m_lat;
double m_lon;
};
In myFunction
I am attempting to cast from the base class to the derived class. 在
myFunction
我尝试从基类myFunction
转换为派生类。
void myFunction(const ThreadedMessage& msg)
{
const GPSMessage* message = static_cast<const GPSMessage*>(&msg); // Compiles fine
const GPSMessage message1 = static_cast<const GPSMessage>(msg); // Error C2440
}
The call to myFunction()
looks like this: 对
myFunction()
的调用如下所示:
GPSMessage msg(21.123, 12.321);
myFunction(msg);
When I compile, the casting of a pointer compiles fine, but the non-pointer casting fails with the following error: 当我编译时,指针的转换可以正常编译,但是非指针的转换失败,并出现以下错误:
error C2440: 'static_cast' : cannot convert from 'const ThreadedMessage' to 'const GPSMessage' No constructor could take the source type, or constructor overload resolution was ambiguous
错误C2440:“ static_cast”:无法从“ const ThreadedMessage”转换为“ const GPSMessage”没有构造函数可以采用源类型,或者构造函数重载解析度不明确
Why am I unable to cast from the base class to the derived class with non-pointer variables? 为什么我不能使用非指针变量将基类转换为派生类?
Compiler is MS VS 2008 C++. 编译器为MS VS 2008 C ++。
Yes, I have looked at other similar SO questions, but the ones I have read don't seem to answer my question. 是的,我看过其他类似的SO问题,但我阅读的问题似乎无法回答我的问题。
These two casts have differing meaning. 这两个角色具有不同的含义。
The first cast: 第一个演员:
const GPSMessage* message = static_cast<const GPSMessage*>(&msg); // Compiles fine
This means that msg
is actually a GPSMessage
(or a derived) object. 这意味着
msg
实际上是GPSMessage
(或派生的)对象。 You ask the compiler to threat msg
as a GPSMessage
. 您要求编译器将
msg
作为GPSMessage
威胁。 No new object will be created, message
will point to msg
. 不会创建新对象,
message
将指向msg
。 If msg
is not actually a GPSMessage
(or derived), then this cast has Undefined Behavior. 如果
msg
实际上不是GPSMessage
(或派生的),则此GPSMessage
Undefined Behavior。
Btw, the following cast have the same meaning (casting to a reference): 顺便说一句,下面的演员表具有相同的含义(铸造参考):
const GPSMessage& message = static_cast<const GPSMessage&>(msg); // same meaning, which results in a reference instead of a pointer
About the second cast: 关于第二个演员表:
const GPSMessage message1 = static_cast<const GPSMessage>(msg); // Error C2440
This means, that you create a new object, message1
from msg
. 这意味着您将创建一个新对象,
message1
msg
message1
。 You should give a way to make this conversion possible. 您应该提供一种使这种转换成为可能的方法。 For example, you should create a constructor for
GPSMessage
which has a ThreadedMessage
parameter: 例如,您应该为
GPSMessage
创建一个具有ThreadedMessage
参数的构造函数:
struct GPSMessage {
GPSMessage(const ThreadedMessage &); // needed constructor
};
Or create a conversion operator for ThreadedMessage
to GPSMessage
: 或创建
ThreadedMessage
到GPSMessage
的转换运算符:
struct ThreadedMessage {
operator GPSMessage(); // conversion operator
};
In the function the compiler only knows that msg
is a reference to a ThreadedMessage
, it doesn't know what's really passed as an argument inside the function. 在函数中,编译器仅知道
msg
是对ThreadedMessage
的引用,而不知道在函数内部作为参数实际传递了什么。
Think about what happened if you passed a reference to an actual ThreadedMessage
object? 想想如果传递对实际
ThreadedMessage
对象的引用会发生什么情况? Or a reference to another object from some other inherited class? 还是从其他继承的类对另一个对象的引用?
To cast from an ThreadedMessage
object to a GPSMessage
object, a conversion is needed, and there's no such conversion possible (the ThreadedMessage
class doesn't have a conversion operator, and GPSMessage
doesn't have a suitable constructor). 要从
ThreadedMessage
对象转换为GPSMessage
对象,需要进行转换,并且这种转换是不可能的( ThreadedMessage
类没有转换运算符,而GPSMessage
没有合适的构造函数)。
The only solution is to cast pointers or references to another pointer or reference. 唯一的解决方案是将指针或引用转换为另一个指针或引用。 Like you do in the pointer example, or by doing eg
就像您在指针示例中所做的那样,或通过例如
const GPSMessage& message1 = static_cast<const GPSMessage&>(msg);
If you really want to cast to a GPSMessage
object , not reference or pointer, then the best solution is to use a conversion constructor: 如果您确实要
GPSMessage
转换为GPSMessage
对象 ,而不是引用或指针,那么最好的解决方案是使用转换构造函数:
class GPSMessage : public ThreadedMessage
{
public:
...
explicit GPSMessage(const ThreadedMessage& tm)
: GPSMessage(static_cast<const GPSMessage&>(tm)) // Invoke copy-constructor
{}
...
};
Using the copy-constructor is nice, but it requires that the tm
argument really is a reference to a GPSMessage
object. 使用copy-constructor很好,但是它要求
tm
参数确实是对GPSMessage
对象的引用。 Otherwise it's invalid. 否则无效。
Another solution is to make the classes polymorphic (simplest by making the destructors virtual
) and use dynamic_cast
to a pointer. 另一个解决方案是使类具有多态性 (通过将析构函数设为
virtual
来dynamic_cast
),并使用dynamic_cast
指向指针。 If the result is a null pointer then msg
wasn't a GPSMessage
to begin with. 如果结果为空指针,则
msg
不是GPSMessage
开头。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.