我正在尝试解决这个问题,但我不知道如何从接口(interface)类转换为我的子类。基本上,我试图将车辆指针数组和数组元素作为子类指针,然后将元素逐个传递给 Counter 类方法,该方法将计算总乘客的值,但我收到编译器错误:
invalid conversion from 'oss:Vehicle*' to 'oss::Bike*' [-fPermissive]
这是我的代码:
车辆.h
using namespace std;
namespace oss{
class Vehicle
{
public:
virtual string type() = 0;
virtual unsigned passengers() = 0;
virtual ~Vehicle();
};
class Land_vehicle : public Vehicle{
protected:
string typeOfVehicle;
unsigned numberOfPassengers;
public:
Land_vehicle();
string type();
};
class Bike : public Land_vehicle{
public:
Bike();
unsigned passengers();
};
class Counter{
private:
int totalPassengers;
public:
Counter();
void add(Bike*b);
int total();
};
车辆.cpp
using namespace oss;
Vehicle::~Vehicle(){};
Land_vehicle::Land_vehicle(){typeOfVehicle = "Land";}
string Land_vehicle::type(){return typeOfVehicle;}
Bike::Bike(){numberOfPassengers = 1;}
unsigned Bike::passengers(){return numberOfPassengers;}
Counter::Counter(){totalPassengers = 0;}
void Counter::add(Bike b){
cout <<"inside add bike"<<endl;
totalPassengers += b.passengers();
}
int Counter::total(){return totalPassengers;}
main.cpp
using namespace std;
using namespace oss;
int main()
{
Counter c;
Vehicle* v[] = {new Bike};
size_t sz = sizeof v/sizeof v[0];
for (unsigned i = 0; i < sz; ++i)
c.add(v[i]);
std::cout << "Total: " << c.total() << " passengers!" << std::endl;
for (unsigned i = 0; i < sz; ++i)
delete v[i];
return 0;
}
最佳答案
根据您的类(class),每Bike
以及每个Car
是Vehicules. THis is why, whenever you need a
车辆* , you can use as well a
自行车* or a
汽车*`。
您在作业中使用了这一点:
Vehicle* v[] = {new Bike}; // yes a Bike* can be converted to a Vehicle*
然而,相反的关系并不成立。不是每个Vehicle
是必要的Bike
。这就是为什么你不能只使用 Vehicle*
当您需要Bike*
时。要执行相反的条件,您首先必须检查Vehicle
您正在使用的确实是 Bike
,如果是这种情况,您可以使用强制转换。
幸运的是,您的类是多态的(由于虚函数)。所以你必须使用 dynamic_cast()
从父(基)指针转换为子(派生)指针。但请注意检查转换是否成功(即强制转换的指针不为空)。
这里出了什么问题?
当您尝试将车辆添加到柜台时,您会遇到此问题及相关问题:
c.add(v[i]); // v[i] is a pointer to a vehicle, but which one
事实上,您的 Counter::add()
有几个问题:
- 首先,您有一个普通对象作为参数,而不是指针。这意味着您需要使用
c.add(*v[i])
取消引用指针。 。但是重载要求您在编译时告知它是哪种类型的对象(即没有add(Vehicle)
,如果有的话,您就会遭受对象切片的困扰) - 然后,如果您使用指针而不是普通对象,则可以使用强制转换:
c.add(dynamic_cast<Bike*>(v[i]);
- 最后,您会意识到,即使使用类型转换,您也会遇到问题:在您的示例中,您发誓阵列中只有一辆自行车。但在实际代码中,您现在无法确定。
第一个解决办法
现在将它们放在一起,以下是如何修改循环以仅将自行车添加到计数器:
for (unsigned i = 0; i < sz; ++i) {
if (dynamic_cast<Bike*>(v[i]))
c.add(dynamic_cast<Bike*>(v[i]));
}
这应该更改添加的签名:
void Counter::add(Bike* b){
cout <<"inside add bike"<<endl;
totalPassengers += b->passengers();
}
这里有一个 live demo
以及解决方案
如果你有多态类,不从多态性中受益是很遗憾的:
class Counter {
int totalPassengers;
public:
Counter();
void add(Vehicle* b);
int total();
};
以及重新设计的功能的实现:
void Counter::add(Vehicle* b){
totalPassengers += b->passengers();
}
无论您从车辆派生多少类,这都将起作用!不再需要添加同一函数的数十个类似重载。
关于C++ 从接口(interface)类到子类的无效转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36959972/