简体   繁体   English

C2440 static_cast无法从基类转换为派生类

[英]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 : 或创建ThreadedMessageGPSMessage的转换运算符:

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. 另一个解决方案是使类具有多态性 (通过将析构函数设为virtualdynamic_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.

相关问题 错误 C2440:“static_cast”:无法从“void (__thiscall Visualizza::*)(char [])”转换为“AFX_PMSG” - error C2440: 'static_cast' : cannot convert from 'void (__thiscall Visualizza::* )(char [])' to 'AFX_PMSG' 什么时候是`static_cast <Base*> (的static_cast <void*> (派生))`从指向派生类的指针有效吗? - When is a `static_cast<Base*>(static_cast<void*>(derived))` from a pointer to a derived class valid? "static_cast 将此对象派生到 C++ 中的基类" - static_cast derived this object to base class in C++ C ++错误C2440:“正在初始化”:无法从“类名”转换为“相同的类名” - C++ error C2440: 'initializing': cannot convert from 'class name' to 'same class name' 如果派生类包含其他方法和成员,那么static_cast可以从基类到派生类完成吗? - Can static_cast be done from base class to derived class if derived class contains additional methods and members? C ++如何在不使用static_cast或dynamic_cast的情况下从基类指针访问派生类成员? - C++ How to access derived class member from base class pointer without using a static_cast or dynamic_cast? C ++嵌套类模板错误C2440&#39;=&#39;:无法从&#39;type&#39;转换为&#39;same type&#39; - C++ Nested class template Error C2440 '=': cannot convert from 'type' to 'same type' 将派生对象中的“this”指针的static_cast用于基类的问题 - Question of using static_cast on “this” pointer in a derived object to base class 从基类指针到派生类指针的static_cast无效 - static_cast from base class pointer to derived class pointer is invalid 当static_cast从派生类到基类时会发生什么? - What happens when static_cast from derived class to base class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM