多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数调用不同内容的函数。多态主要通过联编实现。
静态联编:在编译时一定确定要调用哪个函数。
动态联编:一个类如果有虚函数,它的对象有个指针,指向虚函数表,通过指针调用里面的虚函数。
虚函数表8个字节。
在类的继承的不同层次中,在不同的层次中可以出现名字、参数个数和类型相同而功能不同的函数。编译器按照向自己后父类的顺序进行覆盖查找,如果子类有与父类相同原形的成员函数,要想调用父类的成员函数,需要对父类重新引用调用。虚函数则可以解决子类和父类相同原型成员函数的函数调用问题。虚函数允许在派生类中重新定义域基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类的同名函数。
在基类中用virtual声明成员函数为虚函数,在派生类中重新定义此函数,改变此函数的功能。在C++语言中虚函数可以继承,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。但如果派生类没有覆盖基类的虚函数,则调用时调用基类的函数定义。
覆盖和重载的区别是:重载是同一层次函数名相同,覆盖是在继承层次中成员函数的函数原型完全相同。
根据联编的时刻不同,存在两种类型的多态性。及函数重载和虚函数。
利用虚函数实现多态
多态主要体现在虚函数上,只要虚函数存在,对象类型就会在程序运行时动态绑定。动态绑定的实现方法就是定义一个指向基类对象的指针变量,并使它指向同一类族中函数中需要调用该函数的对象,通过该指针变量调用此虚函数。
基类和子类的对象如何实现调用各自类的函数。通过虚函数实现。
传值得时候
是否可以为虚函数的情况
1.只有类的成员函数才能声明为虚函数。
2.静态成员函数不能是虚函数。
3.内联函数不能是虚函数。
4.构造函数不能是虚函数
5.析构函数一般声明为虚函数。为了调用各自的析构函数。销毁子类的对象会先调用基类的析构函数,在调用子类的析构函数。
6.重载:函数参数不同,不可设为虚函数。
7.覆盖:函数参数,返回值相同,可以设为虚函数。
8.返回值例外:
函数参数相同:但是返回值是当前对象的指针或引用时,也可以设置为虚函数。
#include<iostream>
#include<string.h>
#include<unistd.h>
using namespace std;
class Human{
public:
virtual void eating(void){
cout<<"use hand to eat"<<endl;
}
//void test_eating(Huamn &h);
};
class Englishman:public Human{
public:
void eating(void)
{
cout<<"use knife to eat"<<endl;
}
};
class Chinese:public Human{
public:
void eating(void)
{
cout<<"use chopstickes to eat"<<endl;
}
};
void test_eating(Human &h)
{
h.eating();
}
int main()
{
Human h;
Englishman e;
Chinese c;
test_eating(h);
test_eating(e);
test_eating(c);
return 0;
}
虚拟继承
#include<iostream>
#include<string.h>
#include<unistd.h>
using namespace std;
class Furniture{
private:
int weight;
public:
void setWeight(int weight){
this->weight=weight;
}
int getWeight(void)const
{
return weight;
}
};
class Sofa:virtual public Furniture
{
public:
void watchTV(void){
cout<<"watch TV"<<endl;
}
};
class Bed:virtual public Furniture{
public:
void sleep(void){
cout<<"sleep"<<endl;
}
};
class Sofabed:public Sofa,public Bed{
};
int main(int argc,char *argv[])
{
Sofabed s;
s.sleep();
s.watchTV();
s.setWeight(100);
}
构造函数的顺序:
先父后儿
1.先调用基类的构造函数
1.1先虚拟基类
1.2先一般基类
2.自身
2.1先对象成员
2.2后自己
(虚拟基类构造函数只执行一次)
#include<iostream>
#include<string.h>
#include<unistd.h>
using namespace std;
class Furniture{
private:
int weight;
public:
void setWeight(int weight){
this->weight=weight;
}
int getWeight(void)const
{
return weight;
}
Furniture(){
cout<<"Furniture()"<<endl;
}
};
class Vertification3C{
public:
Vertification3C(){
cout<<"Vertification3C()"<<endl;
}
};
class Sofa:virtual public Furniture,virtual public Vertification3C
{
private:
int a;
public:
void watchTV(void){
cout<<"watchTV"<<endl;
}
Sofa(){
cout<<"Sofa()"<<endl;
}
};
class Bed:virtual public Furniture,virtual public Vertification3C{
private:
int b;
public:
void sleep(void){
cout<<"sleep"<<endl;
}
Bed(){
cout<<"Bed()"<<endl;
}
};
class Sofabed:public Sofa,public Bed{
private:
int c;
public:
Sofabed(){
cout<<"Sofabed()"<<endl;
}
};
class LeftRightCom{
public:
LeftRightCom(){
cout<<"LeftRightCOm()"<<endl;
}
};
class Date{
public:
Date(){
cout<<"Date()"<<endl;
}
};
class Type{
public:
Type(){
cout<<"Type()"<<endl;
}
};
class LeftRightSofabed:public Sofabed,public LeftRightCom{
private:
Date date;
Type type;
public:
LeftRightSofabed(){
cout<<"LeftRightSofabed"<<endl;
}
};
int main(int argc,char *argv[])
{
LeftRightSofabed s;
return 0;
}