#include <iostream>
using namespace std;
class parent
{
public:
parent() { cout << "I am father, constructor" << endl; a = 1; };
virtual void print()//地方1
{
cout << "I am father, working" << endl;
}
private:
int a;
};
class child :public parent
{
public:
child() { cout << "I am child, constructor" << endl; a = 2; };
virtual void print()//地方1
{
cout << "I am child, working" << endl;
}
private:
int a = 0;
};
void print(parent &m)//void print(parent *m)也可以,并且这个参数必须是父类,不能定义为子类
{
m.print();
}
int main()
{
parent m;//地方2
print(m);
child n;//地方2
print(n);
system("pause");
}
一、多态的作用
同样的调用语句根据参数类型不同有多种不同的表现形态。
(面向对象的三大特性另外两个封装和继承,封装主要通过类这个语言结构体现,使得传入的参数信息量更大,除了可以传入一系列成员变量外,还可以传入成员函数,即成员方法。继承主要是能使用已经有的代码量)
二、多态实现的三个条件
1.要有继承关系
2.要有虚函数重写
3.需要将父类指针或者父类引用作为传入函数的参数(一定要注意首先传入的参数必须是父类,子类不可以,其次只能是以指针或者引用的方式,直接传入一个父类变量不可以)
三、多态实现的原理
1.当类中声明虚函数时,编译器会在类中生成一个虚函数表,每一个类都有一个虚函数表,虚函数表是一个存储类成员函数指针的数据结构(地方1处)
2.在创建对象时,编译器会自动生成一个vptr指针,指向虚函数表。(地方2处)
3.在程序编译时,如果检测到使用的类成员函数是虚函数,不会采用静态联编的方式去编译,而是采取动态联编,在程序执行到这一步时,根据类变量的vptr指针找到虚函数表中对应的虚函数执行。
注意:
1.一些概念
联编:是指一个程序模块、代码之间相互关联的过程
静态联编(static binding):是程序的匹配、连接在编译阶段实现,重载函数使用静态联编,一般默认也是静态联编
动态联编:是指程序联编推迟到运行时进行,又称为迟联编。switch和if语句是动态联编的例子
重载overload:是函数名相同,参数列表不同 重载只是在类的内部存在。并且其他参数相同,返回类型不同的函数不属于重载。
重写override:也叫做覆盖。子类重新定义父类中有相同名称和参数的虚函数。函数特征相同。但是具体实现不同,主要是在继承关系中出现的 。
重写需要注意:
1 被重写的函数不能是static的。必须是virtual的
2 重写函数必须有相同的类型,名称和参数列表
3 重写函数的访问修饰符可以不同。尽管virtual是private的,派生类中重写改写为public,protected也是可以的
重定义 (redefining)也叫做隐藏:
子类重新定义父类中有相同名称的非虚函数 ( 参数列表可以不同 ) 。
2.继承构造函数的问题
在结果当中可以看到,子类是继承了父类的构造函数的,子类继承父类构造函数的规则是:
1. 如果子类没有定义构造方法,则调用父类的无参数的构造方法。
2. 如果子类定义了构造方法,不论是无参数还是带参数,在创建子类的对象的时候,首先执行父类无参数的构造方法,然后执行自己的构造方法。
3. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数,则会调用父类的默认无参构造函数。
4. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类自己提供了无参构造函数,则会调用父类自己的无参构造函数。(个人理解是3,4和2一样的意思)
5. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类只定义了自己的有参构造函数,则会出错(如果父类只有有参数的构造方法,则子类必须显示调用此带参构造方法)。
6. 如果子类调用父类带参数的构造方法,需要用初始化父类成员对象的方式,例如fish():animal(400,300),其中fish()是子类的构造函数,animal是父类的构造函数,子类调用父类的有参构造函数,需要按照这种格式。
参考文章:https://www.cnblogs.com/vipchenwei/p/7466018.html?utm_source=debugrun&utm_medium=referral