我是C ++的新手,但我遇到了一个似乎无法解决的问题。 我将使用汽车来说明问题,只是为了让事情变得更容易。 好的,我可以说我有一个基类Car,我有不同的品牌继承自该类。像这样:
class Car
{
public:
Car();
};
class Ford: public Car
{
public:
Ford();
void drive();
void park();
};
整个想法是将所有这些不同的汽车放在一个Car类型的矢量中。像这样:
vector<Car*> cars;
cars.push_back(new Ford());
cars.back()->drive(); //this won't work
如何在基类实例上调用派生函数?请注意,我想将这些全部放在一个向量中。这背后的原因是因为我只想使用已添加的最后一个派生汽车类实例。(在这种情况下,派生的汽车类是福特)。另请注意,所有汽车类都具有相同的功能。
答案 0 :(得分:7)
如果这些函数对所有派生类都是通用的,那么你有一个通用的接口,所以你应该通过基类来表达它。为此,您将这些函数声明为pure-virtual:
class Car {
public:
virtual void drive() = 0; // Pure-virtual function
};
class Ford : public Car {
public:
virtual void drive() { std::cout << "driving Ford\n"; }
};
...
vector<Car*> cars;
cars.push_back(new Ford());
cars.back()->drive(); //this will work
[在旁注中,通常认为使用原始指针向量的做法很差,因为它会使内存管理变得棘手。你应该考虑使用智能指针。]
答案 1 :(得分:3)
您有两种选择:在Car定义中放置虚拟drive()方法,或者将Car指针转换为Ford指针。你有可能想要做第一件事。
class Car
{
public:
Car();
virtual void drive() { // default implementation}
};
现在你可以开车()你的车了!您还可以将drive()设置为纯虚函数,如下所示:
class Car
{
public:
Car();
virtual void drive() = 0;
};
这基本上意味着没有对drive()的默认实现:它必须在子类中重新实现。我提到的第二种方式,再次,你可能不想要,但应该包括完整性,是投射指针:
static_cast<Ford*>(cars.back())->drive();
这只有在事先知道汽车是福特的情况下才有效,但在这种情况下并没有多大用处。您还可以查看dynamic_cast。
答案 2 :(得分:2)
如果所有Car
类具有相同的函数,则在基类virtual
中将它们声明为纯Car
:
class Car
{
public:
Car();
virtual ~Car();
virtual void drive() = 0;
virtual void park() = 0;
};
这将允许使用vector
的示例代码作为已发布的工作。
答案 3 :(得分:0)
如果可能,您可以将基类定义为
class Car
{
public:
Car();
virtual void drive();
};
答案 4 :(得分:0)
您必须定义如下界面:
class Car{
public:
Car();
virtual void moveForward(unsigned int speed) = 0;
virtual void moveBack(unsigned int speed) = 0;
//...
virtual ~Car();
};
不要忘记将析构函数设为虚拟。 之后,您只需要在子类中实现这些方法,然后再调用它们。 同样在向量中,您可以使用shared_ptr或直接传递实例。
答案 5 :(得分:0)
你必须放一个虚函数。
基类中的虚函数。 虚函数可以在子类中实现,因此您可以专门设置drive()的行为。
您可以在此处找到有关虚拟功能的常见问题解答(或教程):
http://www.parashift.com/c++-faq-lite/virtual-functions.html