前言

之前说了多态两种,一种对象多态,一种方法多态
不过一般都是方法多态,也就是一个类中有虚函数。


正文

至于对象多态表面现象也很简单,就是父类和子类之间可以相互转换。
可以互相转化的原理是继承的时候,类在内存之中的表达形式。

现学所知类型转换

  1. 隐式类型转换
  2. 静态强制转换
  3. 动态强制转换

C语言风格就是:(type)这种阔号前置的强制转换类型
c++风格的转换则是:static_cast<type>() 这样
至于隐式转换,整型从小转大,浮点数也是从小到大,整型和浮点型运算,要转换成浮点型。

一切的前提是不加阔号进行人为干预


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class father{
public:

};

class son :public father{
public:

};

int main(){
father *fa;
son s1;
fa = &s1;

return 0;
}

单从类型上是对不上的,但是它发生了隐转,并且是类的向上转型。

1
son *s1 = fa;

而此类操作,属于向下转型,本身指针指向没啥问题,但是这个fa现在是指向了son类型的对象,如果被修改了,那肯定不符合son类型指针指向的问题,所以此处的隐转有风险。
解决的方式就像强制类型转换。

1
son *s1 = (son*)fa;

强制转换是人为设定的,编译器就有可能采取人为的意见去使用它。

1
son *s2 = static_cast<son *>(fa);

静态转换,是c++风格的强制转换。

它与c语言的转换是有分别的。
静态转换的条件

  1. 基类必须是可访问的
1
2
3
4
5
6
7
8
9
class father{
public:

};

class son :father{
public:

};

当没有指定public继承

静态转换就不可用了,而我们的强制转换还是可以用的。

  1. 虚基类
1
2
3
4
5
6
7
8
9
class father{
public:

};

class son :public virtual father{
public:

};

进行向下转换的话,如果是虚基类,不管是静态转换还是强制转换都无法完成。


1
2
3
4
5
6
7
8
9
class pople :public son{

};
class wolf :public son{

};
class werewolf :public pople, public wolf{

};

在隐转的时候,发现三个地址居然有不同。

看到前两个的时候,都是直接取出地址传给eax然后放到指针上,而最后一个则多了很多汇编代码。姑且就是说在最后一个赋值操作的时候,他变成了类型转换的操作。

隐式的转换会存在问题,那么再从void*上强转指针地址又会如何

1
2
3
4
5
6
7
werewolf wf;

void *pt = &wf;
pople *pp = (pople*)pt;
wolf *wl = (wolf*)pt;

std::cout << pt << " " << pp << " " << wl;

看到现在地址一样了。

强制转换的时候,他没有别的操作了,就单纯的把pt的地址传给pp和wl指针。毕竟pt是void类型,强转也没有造成太大影响,基本上就是传递了内存的值。

但是强转如果发生在wf上。

1
2
3
4
5
6
7
werewolf wf;

void *pt = &wf;
pople *pp = (pople*)&wf;
wolf *wl = (wolf*)&wf;

std::cout << pt << " " << pp << " " << wl;

发现地址又不一样了。

然后感觉视频讲的也不明不白的,自己调了一下构造pople和wolf的顺序,顺便改了继承顺序

1
2
3
4
5
6
7
werewolf wf;

void *pt = &wf;
pople *pp = (pople*)&wf;
wolf *wl = (wolf*)&wf;

std::cout << pt << " " << pp << " " << wl;

发现修改顺序之后,werewolf第一个继承的类构造的时候地址会和void*pt是一样的,后面那个就进行一些奇怪的操作。

这让我想起来一个问题
就是空类,实例化之后,他是会占用一个字节的内存的,我不知道这里是不是编译器觉得太多用了一个地址是奇葩操作才给后面那个提升了

暂时留有疑问!


实际上我们这段代码也发生了多重继承,只不过都是空的没啥意义,能够操作的也只有向上转型和向下转型,而且还会碰到不少问题。


结语

??!