簡體   English   中英

從基類指針到派生類指針的static_cast無效

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

我正在創建一個簡單的測試實體組件系統。 我有幾個派生類的基本Component類。 然后,我有幾個將某些邏輯應用於這些組件的系統。

// 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...
        }
    }
}

當我從基本Component* static_cast到任何派生組件( PositionComponent*ControlComponent* )並且兩個結果都不為nullptr (即nullptr成功),我得到了無效值,例如cc->input無法讀取字符串等字符

我將實體工廠中的組件連接起來,如下所示:

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

並且addComponent的實現如下:

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

這些組件顯示為具有有效的內存地址,因此我不確定問題出在哪里。

static_cast在運行時不檢查有效性; 如果強制轉換已編譯,則它將在運行時假定轉換正常。 如果您不強制轉換為空指針,則static_cast的結果將不會為空指針。 要獲得檢查的dynamic_cast轉換,您需要dynamic_cast而這又要求將指針轉換為指向多態類型,即具有至少一個虛函數的類型。 這意味着將Component更改為至少具有一個虛擬功能。

當我從基本Component* static_cast到任何派生組件( PositionComponent*ControlComponent* )並且兩個結果都不為nullptr (即nullptr成功)...

從基類轉換為派生類時, static_cast告訴編譯器:“相信我,我知道我在做什么。” 換句話說,如果它甚至可能合法,它將“成功”並返回non- nullptr 如果在運行時不合法,則嘗試使用一個類的實例就像是另一個類的實例那樣,您將獲得未定義的行為。

請改用dynamic_cast

正如Pete Becker和Josh Kelley所說,請使用dynamic_cast並且我相信您還需要將至少一個函數設置為virtual 如果您不這樣做,則編譯器將不會記錄繼承,而且dynamic_cast可能仍會返回nullptr 執行繼承時,建議將類析構函數設為虛擬。 當需要在派生類的析構函數中處置非托管資源並且您只有指向基類的指針時,這也是一種好習慣,只要只要析構函數是虛擬的,就將調用派生類的析構函數。 這里有一篇文章對此進行了解釋: 什么時候使用虛擬析構函數?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM