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 ...
随机推荐
- 如何使用pm2一键部署node应用
准备工作 准备一台linux服务器(本文档以阿里centos为例) 安装nodejs.git.pm2等环境 项目代码 本地已经安装用于连接 Linux 实例的工具,如 Xshell 基本流程 前两步传 ...
- Shell(2)—数组
Shell(2)-数组 常用的 Bash Shell 只支持一维数组,不支持多维数组. 一.概念 Shell 并且没有限制数组的大小,理论上可以存放无限量的数据.Shell 数组元素的下标也是从 0 ...
- CLRCore(CLR核心机制)
JIT--第一次--标记已--存根--调用--查找存根--执行机器码 C#和CIL的关系: C#和N#都是CIL实现,但是彼此不能互通: C#和N#公开不分满足规范,我们才能互通 CLS就是描述多语言 ...
- AllowsTransparency="True" 怎么放大缩小窗体
后台都不用写任何代码! xaml: <Window x:Class="TestNoBorderWindow" xmlns="http://schem ...
- 关于.Net Core 部署在Linux下连接SqlServer数据库超时解决办法
.Net Core 在 Linux 下连接 SqlServer 需要 SqlServer2008 SP3或以上版本,或SqlServer2012,或SqlServer2014. 如果SqlServer ...
- pycharm 取消连按两下shift出现的全局搜索
在来回切换中英文输入法的时候连按两下shift总是会蹦出来全局搜索框 真的很是麻烦,现在是把这个框给禁用掉 1.按ctrl+shift+a,弹出搜索框2.输入registry,然后按回车3.找到“id ...
- Python小工具:3秒钟将视频转换为音频
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: pk 哥 PS:如有需要Python学习资料的小伙伴可以加点击下方 ...
- fwrite(): send of 8192 bytes failed with errno=104 Connection reset by peer
问题:fwrite(): send of 8192 bytes failed with errno=104 Connection reset by peer 问题描述 通过mysql + sphinx ...
- C# ZedGraph实时多条曲线数据更新实例
C# ZedGraph实时多条曲线数据更新实例 先看展示效果 1.创建曲线实例添加必要的元素 public class LineChannel { public LineChannel(int id, ...
- javascript常用数据验证函数
正则表达式日期验证函数 function CheckDate(str){ //在JavaScript中,正则表达式只能使用"/"开头和结束,不能使用双引号 ...