无法从基类指针访问子类方法

Posted

技术标签:

【中文标题】无法从基类指针访问子类方法【英文标题】:Unable to access subclass methods from baseclass pointer 【发布时间】:2018-08-01 20:45:30 【问题描述】:

不确定我的继承在哪里出错,但我似乎只能在将子类实例存储在基类指针中时访问基类的方法:

class Car

    public:
        Car():type("Car") ;
        Car(const char* t):type(t) ;
        void get_type() const  return this->type; ;
    private:
        std::string type;
;

class Ford : public Car

    public:
        Ford():Car("Ford"), doors(4) ;
        Ford(int x):Car("Ford"), doors(x) ;
        void get_doors() const  return this->doors; ;
    private:
        int doors;
;

int main()

    Car* c = nullptr;
    c = new Ford();
    c->get_doors(); // doesn't exist, only allows for get_type()

这很可能是指针的滥用。我承认 C++ 不是我的强项,所以我试图复制一个用 Python 编写的程序,它大量使用继承,但它比用 C++ 编写的程序简单得多,因为你没有明确使用指针和引用(在抽象级别)。

【问题讨论】:

您可以在Car 中将get_doors() 设为纯虚函数,并在Ford 中覆盖它。但是它不能返回void “抽象类实例化”是什么意思?你不能实例化一个抽象类。 是的,您可以使用Car* 指向来自Car 的派生类的任何实例。但您也仅限于Car 可用的操作。 (因为不能保证你的Car* 指向的东西支持get_doors。想象一下如果第二行是c = new Car();。) 这就是虚函数的用途,正如我在第一条评论中提到的那样。 C++ 是静态类型的,不像 Python 那样具有“鸭子类型”。 试试static_cast<Ford *>(c)->get_doors(); 【参考方案1】:

Python 方法是动态的 - 在 smalltalk 本质上是纯面向对象的。你向一个实例发送一条消息,如果它可以回复它,它就会回复。

C++ 不是这样的。它使用 static 类型。您已声明一个Car* 类型的对象,因此a) 它可以保存指向任何Car 实例或Car 子类型实例的指针,并且b) 它只能被告知这样做可以告诉Cars 做什么。

C++ 也有 virtual 方法。如果在Car 中声明的方法是虚拟的,那么它可以在Car 的子类中实现(例如,在Ford 中)。然后在通过Car 指针调用时将调用该子类的实现。

【讨论】:

我最终使用了virutal 关键字并阅读了文档,这是有道理的。谢谢! 附录:这样做是因为 C++ 力求让程序只为程序员要求的内容付费。动态调度是有代价的,所以在 C++ 中,你只有在要求时才支付这个价格。【参考方案2】:

这正是应该发生的事情。 Car* 指针仅允许您查看 Car 成员。尝试使用 Ford* 指针来查看 Ford 方法。要了解原因,请考虑您有另一个派生自 Car 的类:

class Honda : public Car 
    // no get_doors() here
    void honk();
;

... 

Car* c = new Honda();
c->get_doors(); // What should happen here???

另一方面,如果您希望每个 Car 拥有自己的门数,您可以做几件事:

你可以在基类中声明一个常量成员:

class Car 
public:
    Car(int num_doors) : m_doors(num_doors) 

    int get_doors() const  return m_doors; 
private:
    const int m_doors;


class Ford : public Car 
    Ford() : Car(4)  // Now every ford has 4 doors


class Honda : public Car 
    Honda() : Car(5)  // and every honda has 5

你可以做的另一件事是在你的基类中声明一个虚函数,并在每个子类中覆盖它:

class Car 
public:
    virtual int num_doors() const = 0;


class Ford : public Car 
    int num_doors() const override  return 4;  // Now every ford has 4 doors


class Honda : public Car 
    int num_doors() const override  return 5;  // and every honda has 5

【讨论】:

我最终使用了virtual 关键字,但没有使用override。相反,我在Car 中声明了virtual get_doors() const ;,然后在Ford 中声明了virtual get_doors() const return this->doors;;。我需要使用override吗? @pstatix:我推荐它。使用override,如果你犯了错误,你会得到一个编译错误。没有它,你会得到奇怪的运行时行为。 确实,虽然override 是可选的,但它只能做好事。见***.com/questions/18198314/…

以上是关于无法从基类指针访问子类方法的主要内容,如果未能解决你的问题,请参考以下文章

C++中子类从基类都继承啥?

强制方法从基类调用子类新方法

C++不能使用从基类继承的getter函数

从基类调用静态函数

如何从基类实例中找出子类?

从基类类型的向量访问派生类方法