实现多态必须满足什么条件

作者: 小王同学加油 | 来源:发表于2016-04-24 17:22 被阅读612次

3 虚函数机制 virtual mechanism
先看代码:

class A
{
public:
 virtual void print() { cout<<"A.."<<endl; }
};
class B : public A
{
public:
 virtual void print() { cout<<"B.."<<endl; }
};
void test4()
{
    A a1; //base
    B  b1;//child 

   a1 = b1;//A::operator= 对象b1赋值给a2
    a1.print(); // prints A
    A& a2=b1;// 引用a2指向b1
    a2.print();//// prints B
}

实现条件:

To get polymorphic behavior in C++, the member functions called must be virtualand objects must be manipulated through pointers or references

Q:

  • 为什么使用派生类和基类对象之间直接赋值不能实现?? 必须用用指针或者引用?
  • 为什么要用虚函数?

A:
为什么使用派生类和基类对象之间直接赋值不能实现?? 必须用用指针或者引用?

要实现多态,必须使用指针或者引用    因为默认的赋值运算符并不会操作虚函数表

验证如下:[ Print C++ vtables using GDB]
1.1 vptr 理解成指针 因为不知道vptr内部结果 采用 gdb x查看变量值
因为给出代码只提供一个函数 只需要打印4字节就可以了
(gdb) p sizeof(int) $10 = 4

1.2 打印 A a1; //base
(gdb) p a1

$11 = (A) { _vptr.A = 0x400e10 <vtable for A+16> }
(gdb) x/4x 0x400e10

0x400e10 <_ZTV1A+16>: 0x00400c9e 0x00000000 0x00004231 0x00000000
(gdb) x/4x 0x00400c9e

0x400c9e <A::print()>: 0xe5894855 0x10ec8348 0xf87d8948 0x400dd7be



父类A::_vptr.A 内容是:
0x400c9e <A::print()>

1.3 打印 B b1;//child
执行构造函数:A() -> B()
初始化_vptr
(gdb) p b1 $12 = (B) { = { _vptr.A = 0x400df0 <vtable for B+16> }, } (gdb) x/4x 0x400df0 0x400df0 <_ZTV1B+16>: 0x00400cc8 0x00000000 0x00000000 0x00000000 (gdb) x/4x 0x00400cc8 0x400cc8 <B::print()>: 0xe5894855 0x10ec8348 0xf87d8948 0x400ddbbe


这说明对象b1.vptr 记录虚函数入口地址 0x400cc8 <B::print()>
只要a1.vptr 指向 b1.******** **vptr 即可 ******

1.4 a1=b1
调用 A::operator=

a1

a1 _vptr 没有发生变化 不可以

是不是复制操作有问题这个别人已经验证了 A& operator = (const B& b) { *(int )this=(int *)&b; return *this; }

依然没有发生变化
1.5 A& a2=b1; 发生发生了什么变化
(gdb) p (B)a2 { = { _vptr.A = 0x400cc8 <B::print()> }, }
(gdb) x/4x 0x400cc8 0x400cc8 <B::print()>: 0xe5894855 0x10ec8348 0xf87d8948 0x400ddbbe

一句话解释: 1.默认的赋值运算符并不会操作虚函数表。 2.要实现多态,必须使用指针或者引用
为什么要用虚函数

如果不没有声明虚函数 同名函数出现覆盖现象!
A& a2=b1;
假如 b1 [AAAA BBBB]
a2 [AAAA]
A& a2=b1; 对象赋值 只是a.成员=b.成员 其他的就发生强制转换 结果 a2 [AAAA]
函数之间不会赋值的就需要一个记录 函数入口地址

图片可能和代码不符 你应该可以看懂 没有虚函数的对象数据布局
成员类型相同:


成员类型相同

成员类型不同(对齐)

成员类型不同需 对齐
有虚函数的对象数据布局
有虚函数的对象数据布局
跟深入地方请查看《Inside the C++ Object Model》
我理解
数据部分:
对象在执行赋值 ==操作时候,如果类型不同会发生强制转换
因此需要相同成员
vptr比较特殊 不能像普通成员一样访问
只能通过指针来实现不同对象赋值
通过命令 gdb x 查看 我只声明一个virtual 因此 n=4
如果有清楚麻烦留言告知!

相关文章

  • 实现多态必须满足什么条件

    3 虚函数机制 virtual mechanism先看代码: 实现条件: To get polymorphic b...

  • Java基础之面向对象

    1.多态,继承,封装 Java实现多态有哪些必要条件?具体怎么实现?多态的实现原理?多态的作用? 答:多态的优点 ...

  • 1.9 多态基本概念

    本小节知识点: 【了解】什么是多态? 【掌握】多态的条件 【了解】多态的优点 1.什么是多态? 什么是多态:多态就...

  • 多态

    优秀文章 菜鸟教程 > Java 多态 说明 多态的前提必须满足继承和重写; 重写 普通手机类: 坏手机类: 现在...

  • C++ 多态的实现和原理

    多态的实现虚函数原理 一、在编译期间实现多态 多态是指在不同的条件下表现出不同的状态,C++中通过重载函数的方法可...

  • 日志分析规则设计

    策略设计如下: 规则适用条件 must 里面的条件都必须满足 must_not 里面的条件都必须不满足 shoul...

  • 对抽象类与接口的一点思考

    前言 之前写了一篇文章 简洁代码之道(1):用多态替代条件语句,有人问实现多态的时候为什么用抽象类而不是接口。当时...

  • 怎样解题-波利亚

    首先,你必须弄清问题 未知数是什么?已知数据是什么?条件是什么?满足条件是否可能?要确定未知数,条件是否充分?或者...

  • 多态

    我们先从几个问题入手 什么是多态? 多态的作用是什么? 如何实现多态? 多态性 多态意味着多重形式,往往表现为一个...

  • kotlin中缀调用和析构声明

    中缀调用 实现中缀调用必须满足下面三个条件: 该函数必须为成员函数或者扩展函数必须只有一个参数使用infix关键字...

网友评论

    本文标题:实现多态必须满足什么条件

    本文链接:https://www.haomeiwen.com/subject/ljyfrttx.html