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 ...
随机推荐
- Jenkins的安装后配置
配置Jenkins server 1.安装插件:选择自定义插件安装 Locale plugin Localization: Chinese (Simplified) Git Subversion HT ...
- C++入门到理解阶段二基础篇(2)——C++注释、变量、常量、关键字、标识符
目录 1.注释 注释作用 注释的方式 2.变量 变量基本知识 定义变量 3.常量 常量基本知识 整数常量 浮点常量 布尔常量 字符常量 字符串常量 常量定义 使用 #define 预处理器. 使用 c ...
- 全栈工程师对Python面试中is和==区别的详细解说!看完真的学到了!
面试实习生的时候,当问到 is 和 == 的区别时,很多同学都答不上来,搞不清两者什么时候返回一致,什么时候返回不一致.本文我们来看一下这两者的区别. 我们先来看几个例子: a = "hel ...
- tornado中传递参数的几种方式
方法一 :tornado路由可以使用正则表达式中的子表达式传递url参数.比如:(r"/member//(\w*)/([01]*)", MemberHandler)匹配以后,tor ...
- 如何给HTML页面的文本设置字符和单词间距
设置字符和单词间距介绍 属性名 单位 描述 letter-spacing px 设置字符间距 word-spacing px 设置单词间距 letter-spacing设置字符间距 letter-sp ...
- QML调用C++
//Login.h #include <QObject> #include <QDebug> class Login : public QObject { Q_OBJECT p ...
- pyecharts和echarts的混合使用
ECharts是一个由百度开发的纯 Javascript 的图表库,pyecharts是某三位大佬将ECharts移植到Python项目中的产物,在Python网站中可以更轻松的接入图表,但是个人感觉 ...
- 字符串和id的转换方法
在项目中经常会遇到一个需求就是字符串和id的转换,比如标签和标签id.因为在存储系统里面存储字符串会比较浪费内存,而存储id会节省内存和提高效率. 问题分解 通过字符串获得id 通过id获得字符串 实 ...
- [Go] gocron源码阅读-go语言web框架Macaron
gocron源码中使用的是马卡龙框架,下面这个就是安装这个框架,和一般的MVC框架很像go get gopkg.in/macaron.v1git clone https://github.com/go ...
- AtCoder - 2282 (思维+构造)
题意 https://vjudge.net/problem/AtCoder-2282 告诉你sx,sy,tx,ty,问从s走到t,再从t走到s,再从s走到t,再从t回到s的最短路,每次只能上下左右选一 ...