静态联编:在编译时确定函数的调用,根据指针或引用的类型来决定调用哪个类的函数,而不是根据指针或引用的实际对象来调用哪个类的函数
动态联编:在运行时确定函数的调用,根据指针或引用的实际指向来决定调用哪个类的函数,而不是根据指针或引用的类型来决定调用哪个类的函数
1.要进行动态联编,要在父类同名函数前面必须加上virtual,子类加不加无所谓,因为父类的虚函数特性会被子类继承
2.虚函数virtual的本质,是增加了一个虚函数指针,这个指针指向底层的虚函数表,虚函数表记录着你函数调用的地址,那么调用这个函数的时候,他会顺着表
找到实际执行的函数
3.为什么要存在virtual, void showData(const Parent *p){ p->show() } 这样通用范围更广,父类对象进入,使用的是父类的show函数,子类对象进入使用的是
子类的show函数。using namespace stdclass Parent
{ public: Parent() { cout<<"Parent()"<<endl; this->privata_data =0; } Parent(int k) { this->privata_data =k; } virtual void show() //加上virtual就是动态联编了 { cout<<"Parent:show"<<this->privata_data<<endl; } void setPrivatadata(int a) { this->privata_data = a; } int privata_data; }; class Sub:public Parent { public: Sub() { cout<<"Sub()"<<endl; this->name = " "; } Sub(const string &name,int k=0):Parent(k) { cout<<"Sub(const string &name,int k=0):Parent(k"<<endl; this->name = name; } void show() { cout<<"Sub:show"<<this->name<<endl; } ~Sub() { cout<<"~Sub()"<<endl; } private: string name; };
void showData(Parent *p) { p->show(); }
int main(int argc, char *argv[]) { #if 1 Parent *p = new Sub;//父类指针指向子类对象 p->show();//静态联编,结果是调用父类的show函数 //动态联编,结果是调用子类的show函数 delete p; #endif #if 1 Sub s; Parent &pref =s; //父类引用子类对象 pref.show(); //静态联编,结果为调用父类的show函数 //动态联编,结果是调用子类的show函数 #endif
#if 1 //父类指针和子类指针都能调用,能够自动找到实际地址 Parent *pa = new Parent; Sub *sa = new Sub; showData(pa); showData(sa); #endif
#if 0 Sub *s = new Parent; 子类不能指向父类(儿子不能打老子) Parent p; Sub &s1 = p; #endif }