静态联编
束定:程序中的操作调用(如函数调用)与执行该操作代码间的关系(简单来说就是在函调用时能找到相应代码的位置)
静态联编就是联编工作在编译阶段完成 也就是在程序运行之前就已经确定好了调用这个函数要去哪找
编译阶段就必须确定程序中的操作调用(如函数调用)与执行该操作代码间的关系
下面代码类B继承类A 创建了一个类A类型的指针pa
先pa指针指向类A对象a 调用f()函数 结果是A 再将pa指向类B对象b的地址 调用f()函数 结果还是A 我们会发现地址变了 但是结果没变
class A
{
public:
void f() { cout << "A" << endl; }
};
class B:public A
{ public:
void f() { cout << "B" << endl; }
};
void main()
{
A* pa = NULL;
A a;
B b;
pa = &a; cout << pa<<endl;
pa->f();
pa = &b; cout << pa<<endl;
pa->f();
}
通过对象指针进行的普通成员函数的调用,仅仅与指针的类型有关,而与此刻指针正指向什么对象无关。要想实现当指针指向不同对象时执行不同的操作,就必须将基类中相应的成员函数定义为虚函数,进行动态联编
动态联编
动态联编就是程序在运行的时候知道该调用哪个函数
相较于静态联编 动态联编在编译时只知道要运行的函数名字 并不能确定要去哪运行代码 只有地址确定了才行 动态联编对成员函数的选择是基于对象的类型
动态联编要求派生类和基类中要动态联编的方法函数的返回值类型,参数个数,参数类型,函数名等都必须相同 如果不满足这些条件,派生类中的虚函数将丢失其虚特性,在调用时进行静态联编。
动态联编 只能通过指针或引用标识对象来操作虚函数
动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数
在基类如果在函数前加了virtual 用基类指针指向子类对象时 如果调用的基类函数有virtual 那就是该函数调用时动态在程序运行时联编 而如果没有加virtual就是静态在编译时联编 不用管该函数是否时通过其他函数调用 如下
f1函数如果加了virtual就是调用C类的 没加就是调用B类的
class A
{
public:
virtual void f() { cout << "A" << endl; }
};
class B:public A
{
public:
virtual void f() { cout << "B" << endl; }
};
void main()
{
A* pa = NULL;
A a;
B b;
pa = &a; cout << pa<<endl;
pa->f();
pa = &b; cout << pa<<endl;
pa->f();
}
如果C类继承B类 B类继承A类 用A类指针指向C类 然后用A类指针调用f函数
因为是指向C类对象 且在A类中f函数是virtual 所以动态调用C类中的f函数 但是C类中没有f函数 所以调用它的父类B类中的f函数 但是由于f函数调用了f1函数 A类中的f1函数又没有virtual 所以在B类的f函数中调用f1函数时不能进行动态联编 就只能调用B类中的f1函数了 如果A类中有virtual 那么就是调用C类中的f1函数
class A
{
public:
virtual void f() { cout << "A" << endl; f1();}
void f1() { cout << "A1" << endl; }
};
class B :public A
{
public:
void f() { cout << "B" << endl; f1(); }
void f1() { cout << "B1" << endl; }
};
class C :public B
{
public:
//void f() { cout << "C" << endl; }
void f1() { cout << "C" << endl; }
};
void main()
{
A* pa = NULL;
A a;
B b;
C c;
pa = &a; cout << pa << endl;
pa->f();
pa = &b; cout << pa << endl;
pa->f();
pa = &c; cout << pa << endl;
pa->f();
}
如果A类中f1函数有virtual 就是调用C类中的f1函数
class A
{
public:
virtual void f() { cout << "A" << endl; f1();}
virtual void f1() { cout << "A1" << endl; }
};
class B :public A
{
public:
void f() { cout << "B" << endl; f1(); }
void f1() { cout << "B1" << endl; }
};
class C :public B
{
public:
//void f() { cout << "C" << endl; }
void f1() { cout << "C" << endl; }
};
void main()
{
A* pa = NULL;
A a;
B b;
C c;
pa = &a; cout << pa << endl;
pa->f();
pa = &b; cout << pa << endl;
pa->f();
pa = &c; cout << pa << endl;
pa->f();
}