C++基础
c++概述
C++是对c的扩展,是c语言的超集。
库是编程模块的集合,可以在程序中调用它们,库对很多常见的编程问题提供了可靠的解决方法,因此可以节约大量的时间和工作量。
c++ 在c语言基础上增加了面向对象和泛型编程的思想。
::双冒号 作为全局作用域
命名空间
namespace命名空间的主要用途, 用来解决命名冲突的问题
1.命名空间下, 可以放 函数, 变量, 结构体, 类
2.命名空间必须定义在全局作用域下
3.命名空间可以嵌套命名空间
4.命名空间是开放的,可以随时向命名空间添加内容,合并并不是覆盖
5.匿名命名空间,namespace, static int m_c; 只能在当前文件使用
6.命名空间可以起别名 namespace xx= VV;
using namespace
using 声明, 注意避免二义性问题
写了using 声明以后,下面这行代码表示看到的sunwu都是KIngGlory下面的
但是 编译器有就近原则
所以会导致二义性
//using编译指令
using namespace KingGlory;//打开房间
KingGlory::sunwu; 指定哪个房间
C++对c的增强
- 全局变量检测增强
- 函数检测增强,参数检测增加,返回值检测增强,函数调用增强
//int getRectS(w, h)
//{
//
//}
- 类型转换检测增强
- struct 增强
struct Person
{
int age;
void plusAge() {age++}; //c语言中不可以加函数
};
- bool 类型增强, c语言中没有bool类型
- 三目运算符增强
a>b?a:b - const增强, c语言可以通过地址来修改值,全局区受到了保护不可以更改,这里的变量时伪常量。
- const c语言中默认是 外部链接 ,c++默认是内部链接, 外部,只要其他文件有就可以找到
- const int b = 20; int *p = (int *)&b; 取地址的话会分配临时内存 ,加上extern 也会分配
- 用变量初始化,也会分配内存,凡是分配内存的, 都可以更改值
- 自定义数据类型,
- 尽量用const 替换define
3. 引用(重点)
3.1 引用的基本用法
引用是C++对c的重要扩充
- 变量名实质上是一段连续内存空间的别名, 是一个标号(门牌号)
- 程序中通过变量名来申请并且命名内存空间
- 通过变量名的名字可以使用存储空间
3.1.1 引用基本语法 Type &别名 = 原名
void test01() {
int a = 10;
int &b = a;
b = 12;
cout << “a=” << a << " b = " << b << endl;
}
3.1.2. 引用必须初始化
void test2() {
int a = 10;
int &b = a;//数组必须初始化
int c = 20;
b = c; //赋值
}
3.1.3.对数组进行引用
void test3()
{
int arr[10];
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
//给数组起别名
int(&pArr)[10] = arr;
for (int i = 0; i < 10; i++) {
cout << pArr[i] << " ";
}
cout << endl;
//第二种方式
typedef int(ARRAYREF)[10]; //一个具有10个元素的类型数组
ARRAYREF &pArr2 = arr;
for (int i = 0; i < 10; i++) {
cout << pArr2[i] << " ";
}
cout << endl;
}
3.2 参数的传递方式
注意事项
- &在此不是求地址运算,而是起标识作用
- 类型标识符是指目标变量的类型
- 必须在声明引用变量时进行初始化
- 引用初始化之后不能改变
- 不能有NULL引用,必须确保引用是和一块合法的存储单位关联
- 可以建立对数组的引用
3.3 引用的本质
引用的本质在C++ 内部实现是一个指针常量
3.4 指针的引用
用一级指针引用,可以代替二级指针
常量引用, 修饰形参为只读
const int &a = 10;会分配内存
封装,继承,多态
类和对象 关系??
- 类是对象的抽象
- 对象是类的实例
内联函数 解决宏缺陷问题
函数声明加了关键字, 函数实现也要加关键字inline
函数重载的基本语法
- 函数名称相同, 在同一个作用域下
- 函数参数个数不同,类型不同,顺序不同
- 函数 的返回值不可以作为函数重载条件
- 函数重载碰到了函数默认参数,注意避免二义性
extern C 浅析
解决了C++语言中调用c语言的代码
ifdef __cplusplus extern “C”{}
C语言下的封装和c++的封装
c语言属性和行为分开,类型检测不够
将属性和行为作为一个整体, 来表示生活中具体的事物
有访问权限
class 和struct唯一区别默认权限不同
class默认是private, struct 默认是public
public 类内类外都可以访问
protected 类内可以,类外不可以
private, 类内可以,类外不可以
对象的析构和构造
初始化和清理
构造函数---->用来初始化的
构造函数没有返回值,没有void, 可以发生重载
析构函数---->用来清理的 对象清理
没有返回,没有void, ~ 不可以发生重载
系统会自动调用构造函数和析构函数, 而且只会调用一次
构造函数的分类及调用
按照参数类型
无参构造(默认构造) 有参构造
按照类型分类
普通构造函数 拷贝构造函数
无参构造写法和调用
Person p1 Person(p1)
构造函数调用方式
括号法调用
默认构造函数不要加()
如果是匿名对象, 如果编译器发现了对象是匿名的,那么在这个代码结束后,就释放这个对象
不能用拷贝对象初始化匿名对象
Person p = 100;隐式类型转换 person p = Person(100)
拷贝构造函数调用实际
- 用已经创建好的对象来初始化新的对象
- 以值传递的方式给函数参数赋值
- 以值传递方式返回局部对象
- release 默认会做优化
构造函数的调用规则
//系统默认提供三个函数, 默认构造, 拷贝构造, 析构函数
//当我们提供有参构造函数, 系统不提供默认构造函数
//系统还会默认的拷贝构造函数
深拷贝和浅拷贝
浅拷贝
同一类型的对象之间可以相互赋值, 使得两个对象的成员变量的值相同, 但两个对象是独立的,这种情况是浅拷贝。
一般情况下,浅拷贝没有任何副作用,但当类中有指针,并且指针指向动态分配的内存空间,析构函数做了动态内存释放的处理,会导致内存问题。
系统默认提供的拷贝构造,会进行简单的值拷贝
如果属性里有指向堆区空间的数据,那么简单的浅拷贝会导致重复释放内存的异常
解决上述问题,需要我们自己提供构造数据,进行深拷贝
初始化列表的基本使用
在构造函数的后面+ : 属性(值。参数)
类对象作为成员的案例
类对象作为类成员的时候,构造顺序现将类对象一一构造, 然后构造自己析构的顺序是相反的。
析构顺序与构造相反
explicit
explicit 关键字,防止构造函数中的隐式类型转换
动态对象创建
void test01()
{
//栈区开辟
Person p1;
Person * p2 = new Person;//堆区开辟
//所有new出来的对象,都会返回该类型的指针
//new 会调用构造
//new 运算符, malloc 函数
delete p2;
//malloc 对应free new 对应delete
//用void *接受对象,无法释放
}
如果在new表达式中使用[],必须在相应的delete表达式中也使用[],如果在new表达式中不适用[], 在delete也不要使用
静态成员变量
在一个类中, 将一个成员变量声明为static, 这种成员称为静态成员变量,无论简历多少个对象都只有一个静态数据的拷贝。静态成员变量属于某个类, 所有对象共享。
静态变量,在编译的时候就分配空间, 对象还没创建的是很好,就已经分配空间。
- 静态成员变量必须在类中声明, 在类外定义
- 静态数据成员不属于某个对象, 在为对象分配空间中国,不包括静态成员所占的空间
- 静态数据成员可以通过类名或者对象名来引用。
静态成员实现单例模式
单例模式——xizhu
- 目的 为了让类中只有一个实例,实例不需要自己释放
- 将默认构造和拷贝构造 私有化
- 内部维护一个指针
- 私有化唯一指针
- 对外提供getInstance方法来访问这个指针
- 保证类中只能实例化一个对象
单例模式–打印机案例
类似xizhu案例
提供打印机接口
4.C++面向对象模型初探
成员变量和函数的存储
C++ 中的“数据” 和处理数据的操作(函数) 是分来存储的
- C++中的非静态尘缘函数直接内含在类对象中,就像c strcut 一样
- 成员函数 虽然内含在class声明之类,却不出现在对象中
- 每一个非内联成员函数只会诞生一个实例
this指针
this指针指向被调用的成员函数所属的对象
编译器会偷偷加入一个this指针
Tips:静态成员内部没有this指针, 静态成员函数不能操作非静态成员变量
- 指针永远指向当前对象
- 解决命名冲突问题
- *this
空指针访问成员函数
如果成员函数没有用到this, 那么空指针可以直接访问成员函数
如果成员函数用到看,就要注意,加判断
常函数 常对象
常函数, void func() const{} 常函数
常函数 修饰的是this指针, const Type * const this
常函数 不能修改this指针执行的值
常对象 在对象前加入 const修饰 const Person p1
常对象不可以调用普通的成员函数, 因为普通的成员函数可以修改其内部成员值
用mutable修饰的关键字在常函数可以修改的
5. 友元函数
让全局的好基友函数作为有缘 全局函数写到类中并且声明
friend void gooGay(Buiding * building);
全局函数 好基友
有元函数 目的访问类中私有成员属性
让整个类做友元类
友元类 是单向的不可传递
6. 强化训练(数组封装类)
#pragma once
#include "stdafx.h"
#include<iostream>
using namespace std;
class MyArray {
public:
MyArray(); //默认构造,容量100
MyArray(int capacity);
MyArray(const MyArray & array);
~MyArray();
//尾插法
void push_back(int val);
//根据索引获取值
int geyData(int index);
//根据索引设置值
void setData(int index,int val);
int getSize();
int getCapacity();
private:
int * pAddress; //指向真正存储数据的指针
int m_Size;//数组大小
int m_Capacity; //数组容量
};
// 强化数组封装.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "MyArray.h"
void test01()
{
//堆区创建数组
MyArray * array = new MyArray(30);
delete array;
}
int main()
{
test01();
system("pause");
return 0;
}