c++对象(二)

考虑下面这种多态情况:

    //thing1的类型已经确定为Library的一个object
    Library thing1; 

    //class Book : public Library{...};
    Book book;

    //thing1 不是一个Book!
    //book被裁切了。
    thing1 = book;
    //调用的是Library::check_in
    thing1.check_in();


    //OK:现在thing2参考到book
    Library &thing2 = book;
    //OK:现在引发的是Book::check_in()
    thing2.check_in();

Book类继承自Library类,如果直接将子类Book的对象赋值给父类对象thing1,则thing1的类型在编译期间就已经确定,其所占的内存就是Library对象的内存,子类对象book会被裁切掉一部分来适应thing1的大小,thing1所调用的函数也只能是Library中的函数,不存在多态的可能。
只有通过pointer和reference的间接处理,才支持面向对象程序设计所需的多态性质。在以上的例子中,thing2的运用就是一个良好的例证。
在面向对象中,需要处理一个未知实例,它的类型虽然有所界定,却有无穷可能。这组类型受限于其继承体系,然而该体系理论上没有深度和广度的限制。原则上,被指定的object的真实类型在每一个特定执行点之前,是无法解析的。在c++中,只有通过pointers和references的操作才能够完成。举个例子:

    //retrieve_some_material函数返回Library的某个子类指针
    Library *px = retrieve_some_material(); 
    Library &rx = *px;

    //描述已知物:不可能有令人惊讶的结果产生
    Library dx = *px;

对于px和rx,你没有办法确定的说出其到底指向何种类型的objects,只能够说它要么是一个Library,要么是其一个子类型。但对于dx,我们可以明确的说它是Library的一个object。
在c++中,多态只存在于一个个的public class体系中。C++通过下列方法支持多态:
1.经由一组隐式的转换操作。例如把一个子类的指针转化为一个指向其父类的指针:
Library *ps = new Book();
2.经由虚函数机制:
ps->check_in();
3.经由dynamic_cast和typeid运算符:

if( Book *pc = dynamic_cast<Book*>(ps)) ...

多态的主要用途是经由一个共同的接口来影响类型的封装,这个接口通常被定义在一个抽象的base class中。例如在Library中,就可以为Book,Video,Puppet等子类型定义一个接口。这个共享接口是以虚函数机制引发的,它可以在执行期根据object的真正类型解析出到底是哪一个函数被调用。

那么,需要多少内存才能够表现一个class object? 一般而言要有:
1.其非静态成员函数的总和大小;
2.加上任何由于alignment的需求而填补上去的空间;
3.加上为了支持virtual而由内部产生的任何额外负担;通常为指向虚函数表的指针(vptr);

对于指针,不管它指向哪一种数据类型,指针本身所需的内存大小是固定的(通常是4字节)。但是,一个指向Library的指针是如何与一个指向整数的指针相区别的呢?
以内存需求的观点来看,没有什么不同!它们都需要足够的内存来放置一个机器地址(通常4字节)。“指向不同类型之各指针”间的差异,既不在其指针表示法不同,也不在其内容(代表一个地址)不同,而是在其所寻址出来的object类型不同。也就是说,“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小:
int *pi; //对于一个指向地址1000的整数指针,在32位机器上,将涵盖地址空间1000~1003;
Library *px; //对于一个Library,如果Library的对象所需的内存空间为16个字节的话,则px指针将横跨地址1000~1015;

加上多态之后

class ZooAnimal
{
public:
    ZooAnimal();
    virtual ~ZooAnimal();
    virtual void rotate();

protected:
    int loc;
    string name;
};

class Bear : public ZooAnimal
{
public:
    Bear();
    ~Bear();

    void rotate();
    virtual void dance();

protected:
    enum Dances {...};

    Dances dances_known;
    int cell_block;
};

Bear b("Yogi");
Bear *pb = &b;
Bear &rb = *pb;

如上的继承体系中,b,pb,rb会有怎样的内存需求呢? 不管是pointer和references都只需要一个word的空间(在32位机器上是4-bytes)。Bear object需要24bytes,也就是父类ZooAnimal的16Bytes加上Bear所带来的8bytes;可能的布局如下:
这里写图片描述
我们假设Bear object放在地址1000处,一个Bear指针和一个ZooAnimal指针会有什么不同呢?

Bear b;
ZooAnimal *pz = &b;
Bear *pb = &b;

它们每个都指向Bear object的第一个byte。在上面提到过,“指针类型”会教导编译器如何解释某个特定地址中的内存内容及其大小。对于pb,所涵盖的地址包含整个Bear object,从1000~1024;对于pz,所涵盖的地址只包含Bear object中的父类ZooAnimal部分,从1000~1016; 因此,除了ZooAnimal中出现的members,你不能够通过pz来直接处理Bear的任何members。唯一例外是通过virtual机制:

    // 不合法:cell_block 不是ZooAnimal的一个member,
    //虽然我们知道pz目前指向一个Bear Object.
    pz->cell_block;

    //Ok:经过一个显示的转换操作就没问题!
    (static_cast< Bear *> (pz))->cell_block;

    //下面这样更好,但它是一个run-time operation (成本较高)
    if (Bear *pb2 = dynamic_cast<Bear*>(pz))
    {
        pb2->cell_block;
    }

    //Ok:因为cell_block是Bear的一个member。
    pb->cell_block;

当我们写

pz->rotate(); 

时,在每一个执行点,pz所指向的object类型可以决定rotate()所调用的实例。类型信息的封装并不是维护与pz之中,而是维护于vptr和vptr所指的虚函数表之间。因此,pz->rotate()会执行Bear 中的rotate函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值