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;
}
那么您的对象就已经根据它们的类型正确分配了。当然,稍后您也可以在程序中使用指针来引用它们。希望对您有所帮助。
这里有这个示例代码:
#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;
}
那么您的对象就已经根据它们的类型正确分配了。当然,稍后您也可以在程序中使用指针来引用它们。希望对您有所帮助。