无法从基类指针访问子类方法
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) 它只能被告知这样做可以告诉Car
s 做什么。
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/…以上是关于无法从基类指针访问子类方法的主要内容,如果未能解决你的问题,请参考以下文章