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 ...
随机推荐
- python-3.8.0 新特性之赋值表达式
[python-3.8.0 新特性之赋值表达式] 赋值表达式的语法是这样的“ name := expression ”,形式上看和赋值语句 “ = ” 差不多,就作用上来看也雷同.也就是说 “:=” ...
- Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失问题分析
最近spring boot项目中由于使用了spring cloud 的hystrix 导致了threadLocal中数据丢失,其实具体也没有使用hystrix,但是显示的把他打开了,导致了此问题. 导 ...
- C#WinForm解决跨线程访问控件属性报错
方式一(在程序初始化构造函数中加一行代码): public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCal ...
- 高强度学习训练第十二天总结:Java hashCode和equals的关系
今天要收拾东西.草草的总结下.. 1.如果两个对象相等,则hashcode一定也是相同的 2.两个对象相等,对两个对象分别调用equals方法都返回true 3.两个对象有相同的hashcode值,它 ...
- 挑战常规 -- 为什么不要再用cookie作为储存?
不要使用cookie当存储 Cookie 是什么? Cookie 由浏览器储存在本地,每次访问目标网址会带上的请求头,服务器可以通过Set-Cookie响应头设置Cookie. Cookie的用途 由 ...
- [转]Outlook VBA自动处理邮件
本文转自:https://blog.csdn.net/hnwyllmm/article/details/44874331 需求描述公司里面每天都会有很多邮件,三分之一都是不需要看的,Outlook的过 ...
- Word模板注入攻击
Word模板注入攻击 0x00 工具准备 phishery:https://github.com/ryhanson/phishery/releases office版本:office 2010 0x0 ...
- 真机调试(A valid provisioning profile for this executable was not found.)
这个问题是因为provisioning的问题,因为真机没有加入到账号下面的原因 解决步骤 1.吧identifier复制然后再平开开发中心 2.点击+号添加设备保存 3.在develope中选中保存即 ...
- [b0007] windows 下 eclipse 开发 hdfs程序样例
目的: 学习使用hdfs 的java命令操作 相关: 进化: [b0010] windows 下 eclipse 开发 hdfs程序样例 (二) [b0011] windows 下 eclipse 开 ...
- ORA-1562 and ORA-1650 Unable to Extend Rollback Segment (Doc ID 1066542.6)
ORA-1562 and ORA-1650 Unable to Extend Rollback Segment (Doc ID 1066542.6) APPLIES TO: Oracle Databa ...