从基类实例调用派生函数的C++方法

9

我对C++还比较新,但遇到了一个问题,似乎无法解决。 为了更好地说明问题,我将使用汽车作为示例。 假设我有一个基类Car,并且有不同的品牌从该类继承。就像这样:

class Car
{
    public:
       Car();
};

class Ford: public Car
{
    public:
        Ford();
        void drive();
        void park();
};

整个想法是将所有不同类型的汽车放在一个名为Car的向量中。如下所示:

整个想法是将所有不同类型的汽车放在一个名为Car的向量中。如下所示:

vector<Car*> cars;
cars.push_back(new Ford());
cars.back()->drive(); //this won't work

我如何在基类实例上调用派生函数?请注意,我想将所有这些放在一个单一的向量中。其原因是因为我只想使用已添加的最后一个派生汽车类实例(在这种情况下,派生汽车类是福特)。还要注意,所有汽车类将具有相同的功能。
6个回答

9
如果这些功能确实是所有派生类共有的,则您需要一个公共接口,因此应通过基类来表达。为此,您应将这些函数声明为纯虚函数:
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
< p >【顺便提一下,通常认为使用指向原始指针的向量是不良实践,因为它会使内存管理变得复杂。您应该考虑使用智能指针。】< /em > < /p >

非常感谢您的快速响应,这解决了问题。 - Dan

4
您有两个选择:要么在您的汽车定义中放置一个虚拟的drive()方法,要么将Car指针转换为Ford指针。很可能您会选择第一个选项。
class Car
{
    public:
       Car();
       virtual void drive() { // default implementation}
};

现在你可以开动你的汽车!你还可以将drive()函数定义为纯虚函数,像这样:

virtual void drive() = 0;

class Car
{
    public:
       Car();
       virtual void drive() = 0;
};

这基本上意味着drive()没有默认实现:它必须在子类中重新实现。我提到的第二种方法,你可能不想用,但为了完整起见应该包括在内,就是将指针强制转换:

static_cast<Ford*>(cars.back())->drive();

只有在事先知道汽车是福特牌时,这种方法才有效,但在这种情况下并没有太大用处。您也可以尝试使用dynamic_cast。


好的,我会使用第一种方法,但知道还有另一种方法也很不错。谢谢你提供的信息! - Dan
1
@Anthony,我认为对于第二种方法,最好使用dynamic_cast而不是static_cast。 - exs

2
如果所有的Car类都具有相同的功能,则在基类Car中将它们声明为纯虚拟函数:
class Car
{
public:
    Car();
    virtual ~Car();
    virtual void drive() = 0;
    virtual void park()  = 0;
};

这将使使用vector的示例代码按原样工作。

0

你必须放置一个虚函数。

在基类中定义一个虚函数。虚函数可以在子类中实现,这样你就可以专门为drive()的行为进行特化。

你可以在这里找到有关虚函数的常见问题解答(或教程):

http://www.parashift.com/c++-faq-lite/virtual-functions.html


0

如果可能的话,您可以将基类定义为

class Car
{
    public:
       Car();
       virtual void drive();
};

0
你需要像这样定义接口:

class Car{
public:
 Car();
 virtual void moveForward(unsigned int speed) = 0;
 virtual void moveBack(unsigned int speed) = 0;
 //...
 virtual ~Car();
};

不要忘记将析构函数声明为虚函数。 之后,您只需要在子类中实现这些方法,并在之后调用它们。 此外,在向量中,您可以使用shared_ptr或直接传递实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接