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 ...
随机推荐
- 关于unittest单元测试框架中常用的几种用例加载方法
unittest模块是Python自带的一个单元测试模块,我们可以用来做单元测试.unittest模块包含了如下几个子模块: 测试用例:TestCase 测试集:TestSuite 加载用例:Test ...
- Spring5源码解析4-refresh方法之invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactory);方法源码如下: protected void invokeBeanFactoryPostProcessors( ...
- hive creating temporary folder on: Error encountered near token 'TOK_TMP_FILE'
执行create tmp.tablename as select .....语句的时候报以下错误: SemanticException 0:0 creating temporary folder o ...
- git clone: HTTP Basic: Access denied 错误
git clone 报 HTTP Basic: Access denied 错误 解决方案: 1. 如果账号密码有变动 用这个命令 git config –-system –-unset creden ...
- maven使用问题总结
maven dependencies 报红叉的问题: 第一种:检查bulid path 里面maven dependencies 是否丢失包 miss jar. 解决方法1:https://blog. ...
- 从HTML开始
<html>:做网页,是一种超文本标记语言. 超文本:既有添加文本的能力,还可以添加图片,视频等多媒体元素. 标记:由标签组成.不同的标签有不同的效果. 开始标签,结束标签. ...
- DYNAMICS 365发布所有时候报错:appmodule With Id = a7a513b1-c87d-e911-a83a-000d3a375321 Does Not Exist
我是微软Dynamcis 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- ABP进阶教程2 - 组合查询
点这里进入ABP进阶教程目录 更新数据传输对象 打开应用层(即JD.CRS.Application)的Course\Dto\GetAllCoursesInput.cs //Course数据传输对象(查 ...
- this license XXXXXX has been cancelled
this license XXXXXX has been cancelled问题解决:首先修改hosts 文件 加入0.0.0.0 account.jetbrains.comhosts 目录 wind ...
- [Linux] docker 方式安装和使用gitlab-ce
gitlab就相当于我们自己内网搭建的git服务,相当于公司内的github. 拉取镜像docker pull gitlab/gitlab-ce 创建宿主机的数据目录mkdir -p /mnt/git ...