C++对象模型笔记-对象

看完C++对象模型之后,感觉还没完全掌握,特此记录一下自己对C++对象模型的一点理解,帮助自己梳理概念。文中都是自己的理解,并不保证正确,参考者慎重。

概述

  • 我先胡扯一下要说的内容,C++对象模型。C++对象模型到底讲述了哪些东西或者说什么是C++对象模型。 C++对象模型包含两部分内容:语言中直接支持面向对象程序设计的部分以及对各种底层实现机制的支持。 这两者相辅相成,C++作为一个面向对象的语言自然需要支持面向对象的相关设计(虽说C++模型和面向对象的思想是一起发展起来的,作为一个新学者就暂且认为先有OO思想吧),当然也逃离不了对面向对象相关机制的实现。
  • 就像达到一个目的地并非只有一种手段,因此也有很多种方法来是实现面向对象的机制。经过多年的发展大家可能默认了一种较为统一的方法,但了解这种方法变更的过程相信也是很有意义的。
  • 在C中数据和方法是分开定义的,虽说可以将数据和函数在同一个源文件中定义,把一个源文件当作一个对象(C中的面向对象的思想),这种OO的思想和具体实现暂且不做过多解释。它在实现对象间关系时比较无力。

举例分析

C和C++实现同样一个功能有不同的方法,以一个坐标的显示为例来展示这种区别。
在C中我们写一个坐标的输出函数
#include<stdio.h>
typedef struct point3d
{
float x;
float y;
float z;
}Point3d;
#define print_point3d(p)printf("(%g,%g,%g)", p.x, p.y, p.z);//定义宏

int main() {
Point3d p = { 0 };
print_point3d(p);
//printf("(%g,%g,%g)", p.x, p.y, p.z);
}
在C++中
Point3d.h文件
#pragma once
#include
using namespace std;
class Point3d {
public:
Point3d(float x = 0.0, float y = 0.0, float z = 0.0)//构造函数 默认参数
:_x(x), _y(y), _z(z) {};//初始化列表 调用float类型的初始化。
float x() const { return _x; };
float y() const { return _y; };
float z() const { return _z; };
friend ostream& operator<<(ostream& output,const Point3d& pt);
private:
float _x;
float _y;
float _z;
};
Point3d.c文件
#include"Pointe3d.h"

ostream&
operator<<(ostream& output, const Point3d& pt) {
return output << “(” << pt.x() << “,” << pt.y() << “,” << pt.z() << “)” << endl;
};
main文件
//#include<stdio.h>
#include"Pointe3d.h"
#include
using namespace std;

int main() {
Point3d p = { 3 ,4,6};
/print_point3d§;/
//printf("(%g,%g,%g)", p.x, p.y, p.z);
cout <<p;
}
ps:如果使用cout<<&p 输出的是地址。

C++对象模型

  • 在C++中友static nonstatic两种成员数据,有static、nonstatic和virtual三种成员函数。
  • C++对象模型

C++对象模型

  • 所有的成员函数和静态成员数据是独立于对象中存在的,并仅有一份。申明类的一个对象时实际上时申明了非静态成员数据和一个虚表。虚表中存有RTTI信息和虚函数的地址信息。

对象模型的扩展

  • 在C++中类和类之间的关系有包含、继承关系。包含关系我们后面再讲述(不会引发对象模型的扩展),先说一下继承关系,类和类之间存在继承关系的话,那么一个类是子类一个类是父类,子类中包含父类中定义的数据。我们的对象模型也要兼容这种特性。
  • 有一种思路就是扩充原有的virtual table,在virtual table中维护每一个virtual base class的位置(在后续Data语义中再详细讨论一下细节)。

对象模型中的多态现象

Library_materials thing;
class Book:public Library_materials{...};
Book book;
如果:
thing1=book;//背后的语义:book被裁切
thing1.check()//调用的是父类的方法
如果不使用对象而是用指针
Library_materials &thing2=book;
thing2.check()//调用的是子类的方法	

对象的大小

表现一个C++class需要多大的大小,在前面我们已经介绍过C++对象模型。所需要的大小就是存储对象模型。主要体现在下面三点
1.存储非静态数据所需的内存;
2.数据对齐所需要的额外空间;
3.支持虚拟所产生的额外负担。

class zooanimals{
public:
zooanimals();
virtual ~zooanimals();
protected:
int loc;
string name;
};
存储一个zooanimals对象会占多大内存?
在32位机器上,一个int 4个字节+string(一个指针,一个长度)8个字节+vtable;

继承情况下的class内存的大小

了解继承体系中的内存布局有助于理解对象模型中的多态现象
class Bear:public zooanimal{
public:
Bear();
~Bear();
protected:
Dance dance_know;
int cell_block;
};
在这里插入图片描述
在发生对象赋值
Bear b(“a”);
zooanimal z=b;
在底层发生了内存代替的行为,将bear中的内容赋值道zooanimal中,函数方法并未发生变化。但vptr并不会指向class bear的vtable。
因此
z.rotate();调用的是zooanimal的函数方法。

这里提几个思考(后续章节我会尝试回答):
1.派生类Bear自己vptr为什么没有体现出来。
2.派生类的虚表和基类的虚表有什么不同。

对象模型的第一章到此结束,如果有理解不对的位置,请各位大佬指出,必定更改。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值