C++ C2440静态_cast无法从基类转换为派生类

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

我试图理解为什么使用指针从基类转换为派生类编译得很好,但使用非指针对象转换会产生错误C2440

下面我有一个基类
ThreadedMessage
,它由class
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;
};
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及更高版本。