对指针来说:
动态类型与静态类型:
动态类型是所指向的对象类型,这发生在程序运行期,静态类型是声明时指针时候,指针本身的类型,这发生在编译期
所以说静态类型声明好后就不发生改变了,动态类型,可以运行改变,也就是允许指向不同的对象类型
如:
//基类
class A
{
public:
//
};
//子类
class B:public A
{
//
};
// pa静态类型为 A ,动态类型也是 A
A *pa = new A();
//pb静态类型为B,动态类型也是B
B *pb = new B();
//paa静态类型为A ,动态类型为B
A *paa = new B();
//pb静态类型为B。指向了A类型,现在动态类型为A
pb = pa;
//B *pbb = new A; 子类指针不能指向基类对象
动态绑定与静态绑定:
有虚函数的地方就是动态绑定,没有虚函数的地方是静态绑定
(根据字面意思理解,静态绑定就是根据静态类型来绑定某种操作,动态类型就是根据动态类型来绑定某种操作)
如:
1 //基类
2 class A
3 {
4 public:
5 virtual void f(int 5)
6 {
7 //....
8 }
9 void f1()
10 {
11 //...
12 }
13 };
14 //子类
15 class B:public A
16 {
17 public:
18 //虚函数重载
19 virtual void f(int 10)
20 {
21 //...
22 }
23 //
24 void f1()
25 {
26 //...
27 }
28 };
29 // pa静态类型为 A ,动态类型也是 A
30 A *pa = new A();
31 //pb静态类型为B,动态类型也是B
32 B *pb = new B();
33 //paa静态类型为A ,动态类型为B
34 A *paa = new B();
根据对象是静态类型(哪一种)还是动态类型(哪一种)确定所调用的函数属于哪个类
对于pa->f(),paa->f()
f()为虚函数,属于动态绑定
因此,由于pa的动态类型为A,所以pa->f()调用的f()为 A::f();
同理,paa的动态类型为B,所以paa->f()所调用的f()为 B::f();
对于pa->f1(), paa->f1()
f1()为非虚函数,属于静态绑定
因此,由于pa ,paa的静态类型均为A,所以其调用的f1()均属于A
对于虚函数,不用重新定义默认实参。因为对于子类和基类对象来说调用的是同一个虚函数,但是如果重新定义默认实参,会导致同一个函数,但是默认实参不同,发生不同的事情
如:
//基类
class A
{
public:
virtual void f(int 5)
{
//....
}
void f1()
{
//...
}
};
//子类
class B:public A
{
public:
//虚函数重载
virtual void f(int 10)
{
//...
}
//
void f1()
{
//...
}
};
A *pa = new A();
B *pb = new B();
pb = pa; //此时pb的动态类型变为A
注意:缺省参数是静态绑定的。
pa, pb 指向同一个对象,但是由于 pa, pb 静态类型分别属于A,B
所以,当出现 pa->f()和pb->f() 时候,它俩动态类型均为A,所调用的f()属于A 类
但是由于缺省参数是和静态类型绑定的,所以 pa->f()中的默认实参是5,pb->f()的默认实参是10, 不同。
故:不要重新定义默认实参。