01关于对象

本文探讨了C++中封装和多态的概念及其实现机制。介绍了C++如何通过类将数据和操作封装在一起,以及虚函数和虚继承的使用。同时,文章还详细解释了多态性的实现原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在C语言中,数据和操作是分开声明的。C++将数据和操作封装在一起。

C++的数据成员包含在类对象中,成员函数不包含在类对象中。非内联函数只产生一个函数实例,内联函数在每一个调用处展开。C++封装数据和操作带来的开销主要由虚函数机制和虚基类函数引起的。还有一些多重继承下的额外负担。

C++有静态和非静态两种数据成员,静态,非静态和虚拟三种成员函数。

简单对象模型为每一个数据成员和成员函数分配一个槽,每个槽中有指针指向数据成员或者成员函数。对象中的成员以槽的索引值来寻址。该模型并没有实际应用,但索引和槽的概念被用于后面的模型。

表格驱动对象模型为对象分配两个槽,分别指向数据成员表格和成员函数表格。成员函数表格中存储了相应的成员。成员函数表格是一些槽,这些槽又分别指向各自的成员函数。这个模型也没有应用,但是成员函数表的概念应用到了虚函数上。

C++对象模型将非静态数据成员放在对象内,静态数据成员放在对象外,静态成员函数和非静态成员函数也放在对象外,虚函数则在对象中放置一个指针vptr,该指针指向一个虚表vtbl,该虚表中存放的是相应虚函数的指针。vptr的设定和修改由类的ctor,dtor和assign自动完成。虚表中的第一个槽用来存放指向type_info对象的指针,该对象用来支持RTTI。

C++对象模型的优点是空间和存取时间的效率,缺点是如果类的非静态数据成员有所修改,应用程序的代码也要重新编译。

在虚拟继承下,基类不管被派生类多少次,永远只有一个实例存在。继承的对象模型在3.4节。

假设类X有一个cctor,vdtor和虚拟foo成员函数,那么下面的代码:

X foobar(){
    X xx;
    X*px=new X;

    xx.foo();
    px->foo();

    delete px;
    return xx;
}

可能被转换为:

void foobar(X&_result){
    _result.X::X();
    px=_new(sizeof(X));
    if(px!=0)
        px->X::X();
    foo(&_result);
    (*px->vtbl[2])(px);
    (*px->vtbl[1])(px);
    _delete(px);
    return;
}

struct和class的区别是struct的访问控制默认是public,class的访问控制默认是private。

把一个子类对象赋给一个父类变量,会发生对象切割。

多态只存在于public类体系中,非public的派生,void*指针不支持。

多态可以把派生类的指针赋给父类指针变量。也可以通过dynamic_cast和typeid运算符:

circle*pc=dynamic_cast<circle*>(ps);

多态的用途是通过一个共同的接口来影响类型的封装,这个接口通常定义在一个抽象的基类中。

类对象大小:

1.非静态数据成员大小

2.对齐填充的大小

3.vptr指针

指针本身的大小是固定的。本质上,一个引用通常是以一个指针来实现的。

void*类型的指针变量只能有一个地址,不能通过它操作所指的对象,因为不知道该对象的地址空间。所以要显式转换,指明所要访问的地址空间的大小。

转换cast是一种编译器指令,它并不 一个指针所含的真正地址,只影响该段内存的大小和内容的解释方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值