C++ dynamic_cast 后期绑定错误 - 切片

C++ dynamic_cast for late binding error - slicing

这里有这个示例代码:

#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 并且显示的程序可以编译,但是当调用 dynamic_cast 时它确实会抛出异常(Access violation).... 我试过使用指针:autos::SUV* suvCar = dynamic_cast<autos::SUV*)(&newCar) 也遇到了访问冲突。

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

是否有更好的方法来获取真实类型或 dynamic_cast 是这里的 only/better 选项?

[编辑 - 解决方案]

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 = 制造车(); 在您的程序中,您只为 Car 对象分配了足够的存储空间。您不能将其转换为占用更多存储空间的子类。

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

例如,

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

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