c++学习笔记之封装篇(上)
一、类对象
假设我们由Tv这个类,定义如下
注意class结尾要加上分号
class Tv()
{
int width;
int height;
int volume;
void changeVolume()
{
//changeVolume
}
};
类的实例化有两种方法,一种是栈中实例化。另一种则是堆中实例化。
而这两种方法除了在用法上有区别以外(区别见下面代码),内存管理也有区别(栈不用考虑内存回收问题,系统会自动回收,而堆则需要程序员主动释放内存)。
1.实例化
- 从栈中实例化对象
Tv tv;
或者
Tv tv[20] //实例化对象数组 从栈中实例化系统自动回收内存
- 从堆中实例化对象
实例化一个对象后还需要判断是否成功申请到内存
Tv *p = new Tv();
Tv *q = new Tv[20]; //开辟一块对象内存
if(p==NULL)
{
cout<<"类实例化失败"<<endl;
}
//从堆中实例化数组对象,需要程序员回收
delete p;
delete[]q;
p = NULL;
q =NULL;
访问数据
- 通过栈实例化的对象访问数据成员:
tv.volume = 5;
tv.changeVolume();
- 通过堆实例化的对象访问数据成员:
tv->volume = 5;
tv->changeVolume();
二、string
可以很方便的定义一个字符串,而不再是使用麻烦的char[]. 使用方法:
// 引入string头文件
#include <string>
初始化方法
注意:第4个初始化方法中的第二个参数只能是一个字符,不能是字符串。
常用操作
对于字符串相加操作,需要注意一点,不能直接使用两个字符串相加,中间必须得有字符串变量连接才行(下面例子中最后一个赋值语句是错误的),具体例子如下:
另外如果要将字符串和整数连在一起输出,则需要在整数前加上 << 进行处理,直接用 “+” 是无效的。
string name;
cin>>name;
cout<<name<<name.size()<<endl;
三、构造函数
- 构造函数必须与类同名,起到的作用与python中的 **_ init > _()** 函数类似,即对类进行数据初始化。
- 构造函数在对象实例化时被自动调用,且只调用一次。
- 构造函数没有返回值,不需要return值。
- 构造函数可以重载。
1. 构造函数分为有参与无参
举个栗子:
class Student
{
// 无参构造函数
Student()
{
m_iHeight = 180;
m_iWeight = 70;
}
// 有参构造函数
Student(int weight, int height)
{
m_iWeight = weight;
m_iHeight = height;
}
private:
int m_iWeight;
int m_iHeight;
}
2. 构造函数初始化列表
在初始化对象时,初始化列表是最先执行的,所以有的时候对于const变量我们也可以提前赋值。
语法: 类名():变量1(参数),变量2(参数){}
用法: 我们都知道一个人的身份证信息一般来说是不能随意篡改的,所以我们会使用const 来修饰,但是因为const修饰后,变量则不能再赋值,但是因为每个人的身份证又不一样,我们不可能在使用const修饰的同时进行赋值,那怎么办呢?所以这里用到了初始化列表来达到这么一个效果,详见下面的代码示例:
class Student
{
// 正确示例
// 初始化列表
Student(string id):m_iId(id)
{
// 初始化成功
}
// 编译会报错
// Student(string id)
// {
// m_iId = id;
// }
private:
const string m_iId;
}
初始化类数组
Coordinate *coorArr = new Coordinate[2]{{1,2},{3,4}};
具体示例
#include <iostream>
using namespace std;
class Coordinate
{
public:
Coordinate(int x,int y):m_iX(x),m_iY(y)
{
cout<<m_iX<<","<<m_iY<<endl;
}
// 打印坐标的函数
void printInfo()
{
cout<<m_iX<<","<<m_iY<<endl;
}
private:
int m_iX;
int m_iY;
};
int main(void)
{
//定义对象数组
Coordinate *coorArr = new Coordinate[2]{{1,2},{3,4}};
//遍历数组,打印对象信息
for(int i = 0; i < 2; i++)
{
coorArr[i].printInfo();
}
return 0;
}
3. 拷贝构造函数
- 不能重载 格式: 类名(const 类名& 变量名)
关于拷贝构造函数更具体的解析参考: C++拷贝构造函数详解
4.析构函数
与构造函数相反,当一个对象的生命周期结束时,C++会自动调用一个特殊的成员函数,即析构函数进行善后工作,对成员变量所占内存进行释放操作。 格式:(不需要参数) ~类名(){}
class Student
{
// 构造函数,初始化列表
Student():m_iId(110){};
// 析构函数,c++可以自动生成
~Student(){};
}
对象的生命历程: 申请内存-->初始化列表-->构造函数-->参与运算-->析构函数-->释放内存
- XCode读取Excel数据(适用于任何数据库)
- ObjectDataSource选择业务对象列表为空的探讨
- ASP.NET Web API自身对CORS的支持: CORS授权检验的实施
- 模版引擎XTemplate与代码生成器XCoder(源码)
- 深度学习让人脸识别准确率不断提升
- 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用
- 小论线性变换
- 谈谈基于OAuth 2.0的第三方认证 [下篇]
- Razor Engine,实现代码生成器的又一件利器
- 谈谈基于OAuth 2.0的第三方认证 [上篇]
- 我所理解的RESTful Web API [Web标准篇]
- ASP.NET Web API中的Controller
- iOS 转场动画探究(二)
- Swift 面向对象解析(二)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法