C++:class
class
类是C++的一个重要概念,也是面向对象的一个重要内容。类的行为类似结构体,但功能比结构体的更强大。类是定义该类对象的一个模板,它告诉我们,一个类应该具有什么内容。
声明、定义
类用关键字class
声明、定义。
class LiF1; // 声明一个类
class LiF2 {}; // 声明并定义一个类
如果仅作声明,在声明之后定义之前,它是一个不完全类型,这时只能定义指向该类型的指针或引用,可以声明但不能定义以该类型作为参数或返回值的函数。在类的名字出现之后,他就被认为是声明过的,因此,可以在类内定义指向自身类型的指针或引用。有时会遇到一些比较复杂的情形,就需要我们先声明一个类,随后再去完善定义。比如:我们需要一个类X包含一个指向类Y的指针,同时,类Y又包含一个类型为X的对象,实现如下:
class X;
class Y {
X* x;
};
class X {
Y y;
};
成员
类内的数据称为类的成员(member),成员包括成员变量和成员函数。成员变量定义类的属性,成员函数定义类的行为。
成员变量
在类内声明的变量称为成员变量。成员变量可以是任何数据类型,甚至可以是指向自身类型的指针或引用。
成员函数
声明在类内部的函数称为成员函数。成员函数的本质也是普通函数,只是编译器帮我们在成员函数的形参列表首部隐式加上了一个指向该类型的指针,即要求该类的对象才能调用。而在调用的时候,编译器也为我们在实参列表加入了this
指针,即指向函数调用对象本身的指针。
class LiF {
public:
void doNothing(){}
// 实际的定义是:void doNothing(LiF *this){}
};
LiF lif;
lif.doNothing();
// 实际的调用是:doNothing(this);
访问权限
在类内,我们可以通过访问权限限定符public
、protected
、private
限制类内成员的访问权限。同一个访问限定符可以出现多次,默认状态下,在第一个访问限定符出现之前,类内的访问权限是private
,在最后一个访问限定符出现之后,所有成员的访问权限都是限定符指定的权限等级。
class LiF {
int a; // a是默认的private权限
public:
int b(); // b()在public限定符下,所以是public权限
protected:
int c; // c在protected限定符下,所以是protected权限
private:
int d; // d在private限定符下,所以是private权限
public: // 允许同一限定符重复出现
int e;
};
对应的权限如下:
public
:可以被类的成员函数、友元、子类的成员函数和友元、类的对象访问;可以被子类以任何方式继承。protected
:可以被类的成员函数、友元函数、子类的成员函数和友元访问,类的对象无权访问;可以被子类以任何方式继承。private
:只能被类的成员函数、友元访问;无法通过任何方式继承。
与java、C#不同的是,C++限定符的限制对象是类,而非类的对象;C++的类也没有访问权限之分。
class LiF {
public:
static int sum(const LiF& l1, const LiF& l2) {
return l1.lif + l2.lif; // 可以直接访问对象的私有成员
}
private:
int lif;
};
LiF l1, l2;
LiF::sum(l1, l2);
内存占用
为了更高效地利用内存,C++采用数据和方法分离的存储方法。即在我们定义类时,程序会为这个类划分一个区域,专门存放这个类的成员函数;而在我们每次定义该类的对象时,程序会按照类的定义为每一个对象都分配一段内存,存储对象数据。也正因此,C++隐式使用对象指针访问成员函数,也出现了this
指针。
对象占用的内存大小由成员变量占用的内存决定。特殊地,如果在类内包含了其他类的对象,那么内存占用会计入被包含对象的大小;如果只是包含其他类的指针,那么就只增加一个指针的占用。如果在类内声明了虚函数,那么需要额外增加4个字节,用于存储虚函数表指针。
class LiF1 {};
sizeof(LiF1); // 结果为1,这是因为这个类没有包含任何数据成员,所以仅仅分配1个字节用于标记类
class LiF2 {
public:
void doNothing(){}
private:
int lif;
};
sizeof(LiF2); // 结果为4,即sizeof(int)
class LiF3 {
public:
virtual void doSomething() = 0;
};
sizeof(LiF3); // 结果为4,这时有虚函数表指针作为类的标记,所以不需要额外的1个字节
class LiF4 {
public:
virtual void doSomething() = 0;
private:
int lif;
};
sizeof(LiF4); // 结果为8,即int的大小+虚函数表指针的大小
class LiF5 {
private:
int a, b;
};
class LiF6 {
private:
LiF5 lif5;
};
sizeof(LiF6); // 结果为8,即sizeof(LiF5)
class LiF7 {
private:
LiF5 *lif5;
};
sizeof(LiF7); // 结果为4,即sizeof(LiF5*)
内存对齐
为了提高存取效率,类的成员变量都是按4字节对齐的。不满4字节的可以合并,超过4字节的只能另起4字节。
class l1 {
char a;
char b;
int c;
};
class l2 {
char a;
int c;
char b;
};
sizeof(l1); // 结果为8
sizeof(l2); // 结果为12
C++:class的更多相关文章
- java web 开发三剑客 -------电子书
Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知In ...
- 所有selenium相关的库
通过爬虫 获取 官方文档库 如果想获取 相应的库 修改对应配置即可 代码如下 from urllib.parse import urljoin import requests from lxml im ...
- In-Memory:内存数据库
在逝去的2016后半年,由于项目需要支持数据的快速更新和多用户的高并发负载,我试水SQL Server 2016的In-Memory OLTP,创建内存数据库实现项目的负载需求,现在项目接近尾声,系统 ...
- 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代
2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...
- 【.net 深呼吸】细说CodeDom(8):分支与循环
有人会问,为啥 CodeDom 不会生成 switch 语句,为啥没生成 while 语句之类.要注意,CodeDom只关心代码逻辑,而不是语法,语法是给写代码的人用的.如果用.net的“反编译”工具 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- App开发:模拟服务器数据接口 - MockApi
为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...
- TODO:macOS编译PHP7.1
TODO:macOS编译PHP7.1 本文主要介绍在macOS上编译PHP7.1,有兴趣的朋友可以去尝试一下. 1.下载PHP7.1源码,建议到PHP官网下载纯净到源码包php-7.1.0.tar.g ...
- In-Memory:在内存中创建临时表和表变量
在Disk-Base数据库中,由于临时表和表变量的数据存储在tempdb中,如果系统频繁地创建和更新临时表和表变量,大量的IO操作集中在tempdb中,tempdb很可能成为系统性能的瓶颈.在SQL ...
- In-Memory:内存优化表的事务处理
内存优化表(Memory-Optimized Table,简称MOT)使用乐观策略(optimistic approach)实现事务的并发控制,在读取MOT时,使用多行版本化(Multi-Row ve ...
随机推荐
- 微信小程序 没有找到可以构建的npm包
问题如图: 1.进入小程序根目录,打开cmd,输入:npm init:然后,输入命令后一直点回车 2.输入命令:npm i vant-weapp -S --production 执行命令完之后,然后再 ...
- Java队列和定时器Timer
一: Queue详解 Queue: 基本上,一个队列就是一个先入先出(FIFO)的数据结构 Queue接口与List.Set同一级别,都是继承了Collection接口.Linked ...
- java高并发系列 - 第4天:JMM相关的一些概念
JMM(java内存模型),由于并发程序要比串行程序复杂很多,其中一个重要原因是并发程序中数据访问一致性和安全性将会受到严重挑战.如何保证一个线程可以看到正确的数据呢?这个问题看起来很白痴.对于串行程 ...
- IntelliJ IDEA UML插件
在IntelliJ IDEA Ultimate 版本中自带了一个UML插件:UMLSupport 查看了Community版本和AndroidStudio 发现没有这个插件. 要使用这个插件导出需要的 ...
- 阿里云centos7安装python3.7.4和pip3
亲测有效,针对 阿里云 centos 7 轻量服务器 python ==> 3.7.4 pip ==> 3 一,打开python官网,找到下载Python的tgz文件,有两种方式下载 ( ...
- zabbix4.0搭建1
server端:负责接受到客户端发送过来的数据,并且保存到自己的数据库当中 端口:10051 agent端:负责每隔一定时间进行客户端的数据采集,并且发送给server端 端口:10050 proxy ...
- css伪类实现行号自动填充
css伪类实现行号自动填充 大多数时候我们需要行号自动填充的时候我们可以 大多数时候是插入元素, 在元素里用js填入行号,或者用 ol > li 实现行号填充, 对于上面的方式,都不太灵活,而且 ...
- 027.[转] 理解OAuth 2.0
作者: 阮一峰 日期: 2014年5月12日 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html OAuth是一个关于授权(authorizat ...
- c语言的全排列
在c语言中实现全排列,对于刚接触c语言,还没学习算法的人来说,比较困难了吧.估计大佬也不会看这种基础的东西,全排列实现的办法很多,在c++中有一个专门的函数可以使用,但是在c中实现就有点困难了.如果你 ...
- MySQL 部署分布式架构 MyCAT (五)
分片(水平拆分) 4.全局表 业务使用场景: 如果你的业务中有些数据类似于数据字典,比如配置文件的配置, 常用业务的配置或者数据量不大很少变动的表,这些表往往不是特别大, 而且大部分的业务场景都会用到 ...