C++ 虚函数的多态性
C++ Polymorphism on Virtual Functions
我试图弄清楚在C++中如何处理继承和多态性,它似乎与我在 Java 中习惯的有点不同。我正在尝试在其中一个函数中返回一个基类,但是当收到返回时,我希望该对象是派生类。但是,它并没有像我预期的那样工作。
#include "Prefixer.h"
using namespace std;
Prefixer::Prefixer( Lexer l ){
lexer = l;
}
Expr Prefixer::expr() {
Expr left = term();
Expr right = termTail();
cout << left.name();
cout << right.name();
return left;
}
Expr Prefixer::term() {
NullExpr temp;
return temp;
}
Expr Prefixer::termTail() {
NullExpr temp;
return temp;
}
但是返回的 left.name() 和 right.name() 都调用 Expr(基类)的虚拟 name() 函数 :C。我怎样才能使它们从派生类 NullExpr 调用重载的 name() 函数?
string Expr::name() {
return "expr";
}
string NullExpr::name() {
return "null";
}
你需要使left
和right
Expr*
或Expr&
,而不是Expr
。
与 Java 不同,类类型的变量C++保存实际实例,而不是对实例的引用。
因此,当您这样做时:
Expr left = term();
您实际上是在调用Expr
的复制构造函数,该构造函数只会创建基Expr
类的一个实例。
在Java中,这是非常不同的 - 你只是设置left
引用一些现有的对象,而不是创建一个新的对象。
因此,需要有left
和right
是引用或指针 - 以便在你习惯于在Java中发生的C++中发生同样的事情。
您的问题始于以下代码:
Expr Prefixer::term()
{
NullExpr temp;
return temp;
}
temp
是一个局部变量,在函数结束时销毁。 返回值通过复制返回表达式temp
来创建一个Expr
实例(因为这是返回类型)。 调用方永远不会看到NullExpr
对象。
Java所做的本质上是:
Expr* Prefixer::term()
{
NullExpr* temp = new NullExpr;
return temp;
}
但是你不能盲目地在C++中这样做,否则你最终会得到内存泄漏(Java有一个垃圾收集器,C++没有)。 您可以使用以下方法释放内存delete
:
Expr* left = term();
left->name();
delete name;
更推荐的方法是使用智能指针,当指向对象的最后一个指针消失时,它会自动销毁对象:
shared_ptr<Expr> Prefixer::term()
{
NullExpr* temp = new NullExpr;
return temp;
}
要使用方法dynamic-binding
(或使用基对象的句柄调用重载子类方法),您应该使用引用或指针操作对象。如果这样实现,请确保返回对象的生存期足够长,以便在方法终止后可以访问它。你会发现它与Java不同,因为Java中的所有对象确实是对堆上存储的引用,而不是对象本身。
- 从基类调用函数的多态性
- C++多态性:有没有办法找到对象成员函数的地址?
- C++ 多态性:如果派生类中的虚函数在基类中声明了常量,是否需要将其声明为常量
- 如果基类指针无法访问派生类成员函数,那么多态性有什么方便的呢?
- 多态性在 lambda 函数C++不起作用
- 多态性是否适用于值?或者在按(基)值返回时使用派生类的移动构造函数
- 如何在保持多态性的同时,将成员函数添加到需要它的继承类中,而不会影响其他同级类?
- C++ 中多态性和函数重载之间的区别
- 函数模板和多态性
- C 多态性实例的构造函数和破坏者
- 多态性(C )的派生类中的超载函数
- 多态性和纯虚函数
- C++ 多态性和非虚函数
- C++多态性/虚拟函数在此不起作用
- 如果重载函数仅被部分重写,则多态性不起作用
- 多态性不适用于相同数据类型(Base和Inherited类)的函数返回值
- 具有引用数据类型的函数多态性
- c++在没有虚拟析构函数的多态性中共享ptr
- 静态多态性中的纯抽象函数等价物是什么
- C++链表/多态性未运行列表函数