【问题标题】:C++ Call derived function from base class instanceC++ 从基类实例调用派生函数
【发布时间】:2012-04-16 00:30:35
【问题描述】:

我对 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

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

【问题讨论】:

    标签: c++ function vector derived-class


    【解决方案1】:

    如果这些函数对所有派生类都是通用的,那么你就有了一个通用接口,所以你应该通过基类来表达它。为此,您将这些函数声明为纯虚拟函数:

    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
    

    [顺便说一句,拥有原始指针向量通常被认为是不好的做法,因为它会使内存管理变得棘手。您应该考虑使用智能指针。]

    【讨论】:

    • 非常感谢您的快速响应,成功了。
    【解决方案2】:

    您有两个选择:在您的 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。

    【讨论】:

    • 是的,我将使用第一种方法,但很高兴知道还有另一种方法。感谢您的信息!
    • @Anthony,我认为对于第二种方法,最好使用 dyanamic_cast 而不是 static_cast
    【解决方案3】:

    如果所有Car 类都具有相同的函数,则在基类Car 中将它们声明为纯virtual

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

    这将允许使用 vector 的示例代码按照发布的方式工作。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        你必须像这样定义接口:

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

        不要忘记将析构函数设为虚拟。 之后你只需要在你的子类中实现这些方法,然后调用它们。 同样在向量中,您可以使用 shared_ptr 或直接传递实例。

        【讨论】:

          【解决方案6】:

          你必须放一个虚函数。

          基类中的虚函数。 可以在子类中实现虚函数,因此您可以专门化 drive() 的行为。

          您可以在此处找到有关虚函数的常见问题解答(或教程):

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

          【讨论】:

            猜你喜欢
            • 2019-07-16
            • 2016-07-06
            • 2011-01-08
            • 2018-10-21
            • 2011-06-19
            • 2016-05-24
            • 2013-07-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多