C++:ObjectSlicing和多态

ObjectSlicing和多态

前置知识

多态不过多介绍,在之前写的文章中有讲到,主要从这两方面理解到多态即可:

1.虚指针(vptr)和虚表(vtbl)

2.动态绑定和静态绑定

ObjectSlicing对象切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Pet
{
string pname;
public:
Pet(const string& name):pname(name){}
virtual string description() {return "this is a pet";}
};

class Dog:public Pet
{
string act;
public:
Dog(const string& name, const string& movement):Pet(name), act(movement){}
virtual string description() {return "this is a dog";}
};

void describe_obj(Pet x)
{
cout<<x.description()<<endl;
}

void describe_ptr(Pet* x)
{
cout<<x->description()<<endl;
}

void describe_ref(Pet& x)
{
cout<<x.description()<<endl;
}

int main()
{
Pet* x1 = new Pet("why");
Dog* x2 = new Dog("shy", "eating");
//最基本的多态:
describe_ptr(x1);//this is a pet
describe_ptr(x2);//this is a dog

//发生object slicing
describe_obj(*x1);//this is a pet
describe_obj(*x2);//this is a pet

//引用的底层就是指针,所以引用肯定可以做到多态,因此和结果一保持一致
describe_ref(*x1);//this is a pet
describe_ref(*x2);//this is a dog

return 0;
}

这个例子告诉我们一些事情:

  • 这就是必须使用指针或者引用来实现多态的原因,值传递会造成ObjectSlicing
  • 指针可以做到多态的原因是指针可以动态绑定其他类型,比如pet指针可以动态绑定dog对象,那么此时这个指针的动态类型就是dog了,静态类型是pet。Pet* p = new Dog()
  • 虚函数绑定的是对象的动态类型