C++中基类和派生类遵循类型兼容原则:即可用派生类的对象去初始化基类的对象,可用派生类的对象去初始化基类的引用,可用派生类对象的地址去初始化基类对象指针。
C++中动态绑定条件发生需要满足2个条件:
1:只有指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,非虚函数不能进行动态绑定
2:必须通过基类类型的引用或指针进行函数调用
基类类型引用和指针的关键点在于静态类型和动态类型可能不同:
1:什么是静态类型?就我的理解来说,所谓的静态类型是指,当我们用上述引用或指针去调用非虚函数是,这时的引用和指针就是引种静态类型的,它对非虚函数的调用是在编译时就确定了
2:从静态类型的对立来看,所谓的动态类型也很明显,当这个引用或指针调用了虚函数时,它就是动态类型,它的行为要到程序运行时才能定义
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d ", x) #define lowbit(x) (x)&(-x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("d.out", "w", stdout) #define ll unsigned long long #define M 100007 #define N 100007 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; const ll R = ((1uLL<<63) - 1); class A { public: A(){} virtual void test() { printf("form A's functuion1 "); } }; class B: public A { public : B(){}; void test() { printf("form B's functuion 2 "); } }; int main() { // Read(); B b; b.test(); //用派生类的对象去初始化基类的对象 A a = b; a.test(); //用派生类对象的地址去初始化基类对象指针 A *ta = new A; ta = &b; ta->test(); //用派生类的对象去初始化基类的引用 A &tta = b; tta.test(); return 0; }
运行以上程序我们会发现将用派生类的对象去初始化基类的对象时,没有存在动态绑定,而是直接调用了基累的函数。其实我们上边提到了,发生动态绑定的第二个条件已经说了,必须是基累的引用或者指针。如果用对象直接初始化的化会自动调用基类的复制构造函数或者重载的赋值操作符。进行截断处理把不属于基类的派生类中的部分去掉。