C++ C2440静态_cast无法从基类转换为派生类
我试图理解为什么使用指针从基类转换为派生类编译得很好,但使用非指针对象转换会产生错误C2440 下面我有一个基类C++ C2440静态_cast无法从基类转换为派生类,c++,casting,polymorphism,static-cast,C++,Casting,Polymorphism,Static Cast,我试图理解为什么使用指针从基类转换为派生类编译得很好,但使用非指针对象转换会产生错误C2440 下面我有一个基类ThreadedMessage,它由classGPSMessage继承 struct ThreadedMessage { ThreadedMessage() : m_Type(0), m_ID(0) { } ThreadedMessage(uint Type, uint ID = 0) : m_Type(Type), m_ID(ID) { } u
ThreadedMessage
,它由classGPSMessage
继承
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;
};
在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
}
编译时,指针的强制转换可以正常编译,但非指针强制转换失败,出现以下错误:
错误C2440:“static_cast”:无法从“const ThreadedMessage”转换为“const GPSMessage”。没有构造函数可以采用源类型,或者构造函数重载解析不明确
为什么我不能用非指针变量从基类强制转换到派生类
编译器是MS VS 2008 C++。
是的,我看过其他类似的SO问题,但我读过的那些问题似乎没有回答我的问题。在函数中,编译器只知道
msg
是对线程消息的引用,它不知道函数中真正传递的参数是什么
考虑一下,如果您传递了对实际ThreadedMessage
对象的引用,会发生什么?或者从其他继承类引用另一个对象
要将ThreadedMessage
对象转换为GPSMessage
对象,需要进行转换,但不可能进行这种转换(ThreadedMessage
类没有转换运算符,而且GPSMessage
没有合适的构造函数)
唯一的解决方案是将指针或引用强制转换为另一个指针或引用。就像您在指针示例中所做的那样,或者通过执行例如
const GPSMessage& message1 = static_cast<const GPSMessage&>(msg);
使用复制构造函数很好,但它要求tm
参数实际上是对GPSMessage
对象的引用。否则无效
另一种解决方案是使类具有多态性(最简单的方法是使析构函数成为虚拟的),并对指针使用动态转换。如果结果是空指针,那么msg
一开始就不是GPSMessage
。在函数中,编译器只知道msg
是对ThreadedMessage
的引用,它不知道函数中真正传递的参数是什么
考虑一下,如果您传递了对实际ThreadedMessage
对象的引用,会发生什么?或者从其他继承类引用另一个对象
要将ThreadedMessage
对象转换为GPSMessage
对象,需要进行转换,但不可能进行这种转换(ThreadedMessage
类没有转换运算符,而且GPSMessage
没有合适的构造函数)
唯一的解决方案是将指针或引用强制转换为另一个指针或引用。就像您在指针示例中所做的那样,或者通过执行例如
const GPSMessage& message1 = static_cast<const GPSMessage&>(msg);
使用复制构造函数很好,但它要求tm
参数实际上是对GPSMessage
对象的引用。否则无效
另一种解决方案是使类具有多态性(最简单的方法是使析构函数成为虚拟的),并对指针使用动态转换。如果结果是空指针,那么msg
一开始就不是GPSMessage
。这两种类型转换的含义不同
第一组演员:
const GPSMessage* message = static_cast<const GPSMessage*>(&msg); // Compiles fine
关于第二组演员:
const GPSMessage message1 = static_cast<const GPSMessage>(msg); // Error C2440
或者为ThreadedMessage
到GPSMessage
创建一个转换运算符:
struct ThreadedMessage {
operator GPSMessage(); // conversion operator
};
这两种类型有不同的含义
第一组演员:
const GPSMessage* message = static_cast<const GPSMessage*>(&msg); // Compiles fine
关于第二组演员:
const GPSMessage message1 = static_cast<const GPSMessage>(msg); // Error C2440
或者为ThreadedMessage
到GPSMessage
创建一个转换运算符:
struct ThreadedMessage {
operator GPSMessage(); // conversion operator
};
如果非常确定msg
的类型,则const GPSMessage message1=static_cast(msg)
即使不修改GPSMessage
,也能正常工作。感谢您提醒我们有关虚拟析构函数的信息。它提醒我所有的类都缺少虚拟析构函数
即使不修改GPSMessage
,也能正常工作。感谢您提醒我们有关虚拟析构函数的信息。它提醒我,所有的类都遗漏了虚拟析构函数。另一方面,你是否考虑过将VC 2008升级到更现代的东西?新版本的MSVC对错误报告和遵循C++标准有很大改进。更不用说对c++11、c++14和c++17MS VS 2008的支持了,VS的最后一个版本支持了我正在开发的系统。另外,对于许多系统C++和11是不允许或支持的。在另一方面:你是否考虑将VC 2008升级到更现代的东西?新版本的MSVC对错误报告和遵循C++标准有很大改进。更不用说对c++11、c++14和c++17MS VS 2008的支持了,VS的最后一个版本支持了我正在开发的系统。此外,对于许多系统,不允许或不支持C++11及更高版本。