用于后期绑定(bind)错误的 C++ dynamic_cast - 切片

标签 c++ inheritance casting dynamic-cast

这里有这个示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>

namespace autos
{
    enum CarTypes
    {
        SUVType,
        SportType,
        UnknownType
    };

    class Car
    {
        public: 
            Car();
            virtual ~Car();

            CarTypes type;
            int powerCV;
    };

    Car::Car()
    {
        type = CarTypes::UnknownType;
    }

    Car::~Car() {}

    class SUV : public Car
    {
        public: 
            SUV();
            virtual ~SUV();

            bool fourXFour;
            int  trunkSizeLiters;
            bool dvdInBackSeat;
    };

    SUV::SUV() 
    {
        type = CarTypes::SUVType;
        powerCV = 0;
        fourXFour = false;
        trunkSizeLiters = 0;
        dvdInBackSeat = false;
    }

    SUV::~SUV() {}

    class Sport : public autos::Car
    {
        public:
            Sport();
            virtual ~Sport();

            bool convertible;
            bool twoSeats;
            int  maxSpeed;
    };

    Sport::Sport() 
    {
        type = autos::CarTypes::SportType;
        powerCV = 0;
        convertible = false;
        twoSeats = false;
        maxSpeed = 0;
    }

    Sport::~Sport() {}
} /* end namespace autos */


autos::Car ManufactureCar()
{
    srand(time(NULL));
    int typeCode = rand() % 2 + 1;

    if (typeCode == 1)
    {
        autos::SUV newSUV;
        newSUV.powerCV = 300;
        newSUV.fourXFour = true;
        newSUV.trunkSizeLiters = 500;
        newSUV.dvdInBackSeat = true;
        return newSUV;
    }

    autos::Sport newSport;
    newSport.powerCV = 550;
    newSport.maxSpeed = 300;
    newSport.twoSeats = true;
    newSport.convertible = true;
    return newSport;
}

int main(int argc)
{
    autos::Car newCar = ManufactureCar();

    if (newCar.type == autos::CarTypes::SportType)
    {
        std::cout << "A new SPORT car was manufactured: " << std::endl;

        autos::Sport& sportCar = dynamic_cast<autos::Sport&>(newCar);

        std::cout << "Power (CV): " << sportCar.powerCV << std::endl;
        std::cout << "Convertible: " << sportCar.convertible << std::endl;
        std::cout << "Maximum speed: " << sportCar.maxSpeed << std::endl;
        std::cout << "Two seats: " << sportCar.twoSeats << std::endl;
    }
    else if (newCar.type == autos::CarTypes::SUVType)
    {
        std::cout << "A new SUV car was manufactured: " << std::endl;

        autos::SUV& suvCar = dynamic_cast<autos::SUV&>(newCar);

        std::cout << "Power (CV): " << suvCar.powerCV << std::endl;
        std::cout << "4x4: " << suvCar.fourXFour << std::endl;
        std::cout << "Trunk size (Liters): " << suvCar.trunkSizeLiters << std::endl;
        std::cout << "DVD in backseats: " << suvCar.dvdInBackSeat << std::endl;
    }
    else
    {
        std::cout << "ERROR: Unknown car manufactured." << std::endl;
    }

}

我看过 this post here并且显示的程序可以编译,但是当 Access violation 时它确实抛出异常( dynamic_cast )叫做.... 我试过使用指针:autos::SUV* suvCar = dynamic_cast<autos::SUV*)(&newCar)并且还遇到了访问冲突。

为什么我无法将数据转换为派生类型?

有没有更好的方法来获取真实类型或dynamic_cast是这里唯一/更好的选择吗?

[编辑 - 解决方案]

Problem solved using smart pointers:

std::shared_ptr<autos::Car> ManufactureCar()
{
    srand(time(NULL));
    int typeCode = rand() % 2 + 1;

    if (typeCode == 1)
    {
        autos::SUV newSUV;
        newSUV.powerCV = 300;
        newSUV.fourXFour = true;
        newSUV.trunkSizeLiters = 500;
        newSUV.dvdInBackSeat = true;

        auto ret = std::make_shared<autos::SUV>(newSUV);
        return std::dynamic_pointer_cast<autos::Car>(ret);
    }

    autos::Sport newSport;
    newSport.powerCV = 550;
    newSport.maxSpeed = 300;
    newSport.twoSeats = true;
    newSport.convertible = true;

    auto ret = std::make_shared<autos::Sport>(newSport);
    return std::dynamic_pointer_cast<autos::Car>(ret);
}

int main(int argc)
{
    std::shared_ptr<autos::Car> newCar = ManufactureCar();

    if (newCar->type == autos::CarTypes::SportType)
    {
        std::cout << "A new SPORT car was manufactured: " << std::endl;

        std::shared_ptr<autos::Sport> sportCar = std::dynamic_pointer_cast<autos::Sport> (newCar);

        std::cout << "Power (CV): " << sportCar->powerCV << std::endl;
        std::cout << "Convertible: " << sportCar->convertible << std::endl;
        std::cout << "Maximum speed: " << sportCar->maxSpeed << std::endl;
        std::cout << "Two seats: " << sportCar->twoSeats << std::endl;
    }
    else if (newCar->type == autos::CarTypes::SUVType)
    {
        std::cout << "A new SUV car was manufactured: " << std::endl;

        std::shared_ptr<autos::SUV> suvCar = std::dynamic_pointer_cast<autos::SUV> (newCar);

        std::cout << "Power (CV): " << suvCar->powerCV << std::endl;
        std::cout << "4x4: " << suvCar->fourXFour << std::endl;
        std::cout << "Trunk size (Liters): " << suvCar->trunkSizeLiters << std::endl;
        std::cout << "DVD in backseats: " << suvCar->dvdInBackSeat << std::endl;
    }
    else
    {
        std::cout << "ERROR: Unknown car manufactured." << std::endl;
    }

}

最佳答案

你在哪里 autos::Car newCar = ManufactureCar(); 在您的程序中,您只为 Car 对象分配了足够的存储空间。您不能将其转换为占用更多存储空间的子类。

我建议您修改 ManufactoreCar() 函数以在堆上创建适当的对象并返回指向该对象的指针。

例如,

   if (typeCode == 1)
    {
        autos::SUV* x = new autos::SUV;
        x->powerCV = 300;
        x->fourXFour = true;
        x->trunkSizeLiters = 500;
        x->dvdInBackSeat = true;
        return x;
    }

然后你的对象就已经根据它们的类型正确分配了。当然,稍后您也可以在程序中使用指针来引用它们。我希望这会有所帮助。

关于用于后期绑定(bind)错误的 C++ dynamic_cast - 切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36135587/

相关文章:

c++ - 使用 STL vector 创建矩阵

c++ - 什么时候类型会提升为无符号整型?

swift - 从字符串中检索的强制转换类类型

c# - 在运行时将对象转换为字符串数组

将 shared_ptr 传递给 lambda 时的 C++ 内存管理

c++ - 手动输入文件名 ifstream

C++:类如何将自身加载到内存中以增加全局变量?

delphi - 如何从具有 protected 数据类型的类继承?

Javascript继承和函数覆盖

带自定义included_tags的Django模型继承