一、多态怎么实现的?
多态按字面的意思就是多种形态,相同的方法调用,但是有不同的实现方式(多态性是指用一个名字定义不同的函数,这些函数执行不同但又类似的操作,这样就可以用同一个函数名调用不同内容的函数)。多态性可以简单地概括为“一个接口,多种方法”。C++有两种多态形式:静态多态和动态多态。
在C++中,多态性的实现和联编(也称绑定)这一概念有关。一个源程序经过编译、链接,成为可执行文件的过程是把可执行代码联编(或称装配)在一起的过程。其中在运行之前就完成的联编成为静态联编(前期联编、地址早绑定);而在程序运行之时才完成的联编叫动态联编(后期联编、地址晚绑定)。一般说的多态指的是动态多态。
静态多态和动态多态区别:
a. 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态 ,静态多态的函数地址早绑定 - 编译阶段确定函数地址,例如:函数重载。
b. 动态绑定又称为后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态,动态多态的函数地址晚绑定 - 运行阶段确定函数地址。
C++的多态性用一句话概括就是:1、在基类的函数前加上virtual关键字,2、在派生类中重写该函数,3、运行时采用父类的引用和指针调用多态方法,父类对象本身不能实现多态。
class animal
{
public:
virtual void sleep() //父类虚函数
{
cout << "animal sleep" << endl;
}
void breathe() //父类非虚成员函数
{
cout << "animal breathe" << endl;
}
};
class fish :public animal
{
public:
void sleep(int time) //父类同名函数隐藏(子类重写时参数和父类虚函数不同)
{
cout << "fish sleep " << time << " hours" << endl;
}
void breathe() //父类同名函数隐藏(父类非虚函数)
{
cout << "fish bubble" << endl;
}
};
class cat :public animal
{
public:
void sleep() //子类重写父类虚函数
{
cout << "cat sleep" << endl;
}
void sleep(int time) //父类指针或引用无法访问
{
cout << "cat sleep " << time << " hours" << endl;
}
void breathe() //子类重写父类非虚函数
{
cout << "cat miaomiao" << endl;
}
};
int main() {
animal a;
a.breathe(); //调用animal中的breathe()
fish f;
//f.sleep(); //报错
f.sleep(5);
f.breathe(); //调用fish中的breathe(),实际上是函数隐藏
cat c;
c.sleep();
c.sleep(5); //函数重载
c.breathe();
animal *p = &c;
p->sleep(); //父类指针指向子类对象,动态多态,调用了子类对象cat中的sleep()
//p->sleep(5); //报错,无法调用
animal &p1 = c; //父类引用子类对象,动态多态,调用了子类对象cat中的sleep()
//p1.sleep(5); //报错,无法调用
animal *p2 = &f;
p2->sleep(); //调用父类animal中的sleep()
//p2->sleep(5); //报错,无法调用
system("pause");
return 0;
}
1、函数的覆盖(重写)
覆盖的条件:
基类函数必须是虚函数(使用Virtual关键字进行声明);
发生覆盖的两个函数必须分别位于派生类和基类中;
函数名称与参数列表必须完全一样;
2、函数的重载
函数重载是同一定义域中(即同一个类中)的同名函数,但形参的个数必须不同,包括参数个数,类型和顺序,不能仅通过返回值类型的不同来重载函数。const也可作为函数重载的条件,但只有引用传递和指针传递可以用是否加const来重载。
3、函数的隐藏
隐藏,是指派生类中具有与基类同名的函数(不考虑参数列表是否一样),从而派生类中隐藏了基类的同名函数。
隐藏的两种情况:
① 派生类的函数与基类的函数完全相同(函数名和参数列表都相同),只是基类的函数没有使用virtual关键字。
② 派生类的函数和基类的函数同名,但参数列表不一样,在这种情况下,不管基类的函数声明是否有virtual关键字,基类的函数都将被隐藏。(注意这种情况与函数重载的区别,重载发生在同一个类中)
多态中的注意点:
1:用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。
2:存在虚函数的类都有一个一维的虚函数表叫做虚表,类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。
3:多态性是一个接口多种实现,是面向对象的核心,分为类的多态性和函数的多态性。
4:多态用虚函数来实现,结合动态绑定.
5:纯虚函数是虚函数再加上 = 0;
6:抽象类是指包括至少一个纯虚函数的类。(纯虚函数:virtual void fun()=0;即抽象类!必须在子类实现这个函数,即先有名称,没有内容,在派生类实现内容。)