简体   繁体   English

从基类指针到派生类指针的static_cast无效

[英]static_cast from base class pointer to derived class pointer is invalid

I am creating a simple test entity-component system. 我正在创建一个简单的测试实体组件系统。 I have a base Component class with several derived classes. 我有几个派生类的基本Component类。 I then have several systems that apply some logic to these components. 然后,我有几个将某些逻辑应用于这些组件的系统。

// Component.h
// ------------
class Component
{
public:
    Component();
    ~Component();
}


// ControlComponent.h
// -------------------
#include <string>
#include "Component.h"

class ControlComponent : public Component
{
public:
    std::string input = ""; // store simple input instruction
    ControlComponent();
    ~ControlComponent();
};


// ControlSystem.cpp
void ControlSystem::update(Entity* entity)
{
    vector<Component*>* components = entity->getComponents();

    for (Component* component : *components)
    {
        PositionComponent* pc = static_cast<PositionComponent*>(component);
        ControlComponent* cc = static_cast<ControlComponent*>(component);

        if (pc != nullptr && cc != nullptr)
        {
            std::cout << "Which direction would you like to go?" << std::endl;
            std::string input;
            std::cin >> input;
            cc->input = input; // application breaks here

            // Apply some logic...
        }
    }
}

When I static_cast from base Component* to either of the derived components ( PositionComponent* or ControlComponent* ) and when both results are not nullptr (ie the cast was successful), I get invalid values, like cc->input not being able to read characters from string etc. 当我从基本Component* static_cast到任何派生组件( PositionComponent*ControlComponent* )并且两个结果都不为nullptr (即nullptr成功),我得到了无效值,例如cc->input无法读取字符串等字符

I wire up the components in my entity factory, like this: 我将实体工厂中的组件连接起来,如下所示:

void EntityFactory::wireUpPlayer(Entity* player)
{
    player->addComponent(new HealthComponent());
    player->addComponent(new ControlComponent());
    player->addComponent(new PositionComponent());
}

And the implementation for addComponent is as follows: 并且addComponent的实现如下:

void Entity::addComponent(Component* component)
{
    m_components.push_back(component);
}

These components are shown to have valid memory addresses, so I'm not sure where the issue is coming from. 这些组件显示为具有有效的内存地址,因此我不确定问题出在哪里。

static_cast does not check validity at runtime; static_cast在运行时不检查有效性; if the cast compiled, it assumes at runtime that the conversion is okay. 如果强制转换已编译,则它将在运行时假定转换正常。 If you aren't casting a null pointer, the result of a static_cast will not be a null pointer. 如果您不强制转换为空指针,则static_cast的结果将不会为空指针。 To get a checked cast you need dynamic_cast and that, in turn, requires the pointer being converted to point to a polymorphic type, ie, one that has at least one virtual function. 要获得检查的dynamic_cast转换,您需要dynamic_cast而这又要求将指针转换为指向多态类型,即具有至少一个虚函数的类型。 That means changing Component to have at least one virtual function. 这意味着将Component更改为至少具有一个虚拟功能。

When I static_cast from base Component* to either of the derived components ( PositionComponent* or ControlComponent* ) and when both results are not nullptr (ie the cast was successful)... 当我从基本Component* static_cast到任何派生组件( PositionComponent*ControlComponent* )并且两个结果都不为nullptr (即nullptr成功)...

When casting from a base class to a derived class, static_cast is telling the compiler, "Trust me, I know what I'm doing." 从基类转换为派生类时, static_cast告诉编译器:“相信我,我知道我在做什么。” In other words, if it's even potentially legal, it will "succeed" and return non- nullptr . 换句话说,如果它甚至可能合法,它将“成功”并返回non- nullptr If, at runtime, it's not legal, you'll get undefined behavior, from trying to use an instance of one class as if it were of another class. 如果在运行时不合法,则尝试使用一个类的实例就像是另一个类的实例那样,您将获得未定义的行为。

Use dynamic_cast instead. 请改用dynamic_cast

As Pete Becker and Josh Kelley said, use dynamic_cast and I believe you also need to set at least one function as virtual . 正如Pete Becker和Josh Kelley所说,请使用dynamic_cast并且我相信您还需要将至少一个函数设置为virtual If you do not, the compiler will not record the inheritance and dynamic_cast will likely still return nullptr . 如果您不这样做,则编译器将不会记录继承,而且dynamic_cast可能仍会返回nullptr When performing inheritance, I suggest making the class destructors virtual. 执行继承时,建议将类析构函数设为虚拟。 This is also good practice when unmanaged resources need to be disposed of in the destructor of a derived class and you only have a pointer to the base class, the derived class destructor will only be called so long as the destructors are virtual. 当需要在派生类的析构函数中处置非托管资源并且您只有指向基类的指针时,这也是一种好习惯,只要只要析构函数是虚拟的,就将调用派生类的析构函数。 There was a post that explained it here: When to use virtual destructors? 这里有一篇文章对此进行了解释: 什么时候使用虚拟析构函数?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 什么时候是`static_cast <Base*> (的static_cast <void*> (派生))`从指向派生类的指针有效吗? - When is a `static_cast<Base*>(static_cast<void*>(derived))` from a pointer to a derived class valid? 为什么从指向 Base 的指针到指向 Derived 的指针的 static_cast “无效”? - Why is a static_cast from a Pointer to Base to a Pointer to Derived “invalid?” 将派生对象中的“this”指针的static_cast用于基类的问题 - Question of using static_cast on “this” pointer in a derived object to base class static_cast到base析构函数的指向派生类的安全性 - Safety of static_cast to pointer-to-derived class from base destructor 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 ++ Static_cast指向虚拟基类的指针 - C++ Static_cast over a pointer to virtual base class 通过指向base,static_cast,crtp,删除模板的指针派生的成员 - Member of derived by pointer to base, static_cast, crtp, removing templates 如果派生类包含其他方法和成员,那么static_cast可以从基类到派生类完成吗? - Can static_cast be done from base class to derived class if derived class contains additional methods and members? "static_cast 将此对象派生到 C++ 中的基类" - static_cast derived this object to base class in C++ 当static_cast从派生类到基类时会发生什么? - What happens when static_cast from derived class to base class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM