C++基础笔记

C++基础

因为工作需求学习C++,内容正在不断更新,内容主要来自于网上的视频课
C++是C的超集
C++在C上添加了面向对象编程和泛型编程的思想


一、语法基础

1.1 Hello world实现

1.1.1 命名空间:

using namespace std; 使用命名空间std,理解:打开一个std的房间,房间里有cout等,打开一次代码就可以一直用
也可以通过std::cout<<“hello world”<<endl; 的方式实现,但是每次需要std都需要打开一下房子

1.1.2 阻塞功能

system(“pause”); 让命令窗口保留
return EXIT_SUCCESS 表示代码成功离开,返回正常退出

1.1.3 面向对象三大特性

  • 封装
    把客观对象抽象成类
  • 继承
    父子对象
  • 多态
    一个接口多种方法

1.2 双冒号作用域运算符

在函数里调用全局变量的时候可以使用::[变量名]的方式调用
::前面如果有std或者什么范围,就相当于到对应的范围找

1.3 命名空间的使用

在game1.h文件中

namespace LOL
{
    void goAtk();
}

在game1.cpp文件中

#include "game1.h"
void LOL::goAtk()
{
    cout << "LOL攻击实现" <<endl;
}

在本文件或者其他文件运行的时候:

int main(){
    LOL::goAtk();
}
  • 命名空间内可以放函数、变量、结构体、类
    但是必须定义在全局作用域下,不能在函数内部
  • 命名空间可以嵌套命名空间
namespace A
{
	int a = 20;
	namespace B
	{
		int a = 10;
	}
}
int main()
{
//输出B下的a
cout << A::B::a << endl;
}
//输出为10
  • 命名空间是开放的可以在后续程序继续向里面放内容,会自动合并
namespace A
{
	int a = 20;
}
namespace A
{
	int b = 30;
}
//这时候A里面a和b都有
  • 无名命名空间,相当于static int C; static int D;也就是只能在当前文件内使用
namespace {
	int C = 0;
	int D = 0;
}
  • 命名空间可以起别名
namespace veryLong{
	int C = 0;
	int D = 0;
}
namespace veryshort = veryLong; //即可完成起别名

1.4 using声明和using编译指令

二义性:
避免如下图的情况
在这里插入图片描述

1.5 C++对C语言的增强

  1. 全局变量的检测增强
    以下代码在C中可以跑通,但是在C++不可以
int a;
int a = 10;
  1. 函数检测增强
    以下代码在C中可以跑通,但是在C++不可以(没有参数类型和返回值,参数数量不对)
get(10, 10, 10)
int get(w, h){
}
  1. 类型转换检测增强
    以下代码在C中可以跑通,但是在C++不可以(需要改成char *p = (char *)malloc(sizeof(64));)
void test(){
	char *p = malloc(sizeof(64)); //malloc返回值是void*
}
  1. struct增强
    C中struct不能加函数,C++中可以(void plusAge()😉
struct Person
{
	int Age;
	// void plusAge();
}

定义结构体的时候,C++可以简洁一点
C:

struct Person p;

C++:

Person p;
  1. bool类型增强
    C语言中没有bool类型
    C++有
    非0的bool类型值都默认转为1
    所以不论如何赋值,bool只能存0/1

  2. 三目运算符增强
    常见情况:

int a = 10;
int b = 20;
c = a > b ? a :b;
// c = 20

C++特有允许情况:

int a = 10;
int b = 20;
(a > b ? a : b) = 100;
// a = 10, b = 100, 因为C++的三目运算符返回的是变量(这里是b),C返回的是数值
  1. const增强
  • C语言的const是伪常量
const int a = 10;
// a = 100; C语言这种方式不可以,不能对const直接改值
// 但是C语言用下面指针的方式依旧可以修改a的值,因为编译器是分配内存的方式定义数据
int *p = (int *)&a;
*p = 200;
// a = 200

C++通过上面的方式可以运行,但是a的值没有被改变,a依旧是10
因为C++不是通过分配内存的方式定义数据,利用类似下面的表格存放数据
新开指针的时候会分配一个临时内存
在这里插入图片描述

  • C语言中const默认是外部链接,C++中默认是内部链接
    意思就是说C++中定义的const int a,其他文件调用该文件的时候,不能直接通过extern调用a,定义的时候需要extern const int a;

  • 分配内存情况
    如何防止开辟临时内存导致const无法更改呢
    利用普通变量初始化const的变量

int a = 10;
const int b = a;//会分配内存

int * p = (int *) &b;
*p = 1000;
cout << b <<endl;
//输出为1000
  • 自定义数据类型(比如结构体)
const Person p1;
//p1.m_Name = "aaa"; 这种方式不可以改const修饰的结构体
Person *p = (Person*)&p1;
p->m_Name = "元歌";
(*p).m_Age = 18;
//利用如此的两行就可以全部修改出来

所以C++中,const修饰的变量是可以用于初始化数组的,C中则不可以

1.6 尽量用const代替define

对于下面的语句,MAX从没被编译器看到过,因为在预处理阶段所有的MAX都被自动替换为1024了,所以相关的报错不会提到MAX,而都是1024
define的数没有类型,无法类型检测
const能完全替换define的功能
difine的变量没有作用域,自始而终都存活(虽然可以用#undef MAX 解决)

#define MAX 2014

1.7 引用,意思就是起别名

1.7.1 引用的知识点

  • 语法:
int &b = a;//引用
int b = &a;//取地址

b和a的作用就是等同的了

  • 引用必须初始化
    int &a;这样的代码是不可以的

  • 引用初始化之后不可修改

int &b = a;//引用
b = c;//这行不可执行,报错
  • 对数组建立引用
int arr[10];
int (&pArr)[10] = arr;
  • 引用必须引一个变量等合法空间
int &a = NULL;
int &a = 10;  这两个都是不可以的
  • 引用不能在外部引局部变量
    (static int a可以解决下面的问题)
    在这里插入图片描述

1.7.2 引用的本质

引用在C++内部的实现是一个指针常量
在这里插入图片描述

1.7.3 指针的引用

可以有效避免二级指针的使用
在这里插入图片描述

1.7.4 常量的引用

int &a = 10;    不合法的引用
const int &a = 10;   合法的引用,因为在加入const之后,编译器的处理方式是 int tmp = 10;const int &a = tmp;
int *p = (int *)&a;
*p = 1000;
在上面两行的操作之后,a的值就变成1000

1.8 参数的传递方式

值传递
地址传递
引用传递

二、函数和封装

2.1 对象中函数的设计

一个简单的求圆周长的程序
Public能够让对象的东西可以在外部访问

#include <iostream>
using namespace std;
const double pi = 3.14;
//设计一个圆的类然后求周长
class Circle{
public ://公共权限
    int r;//成员属性
    double cal_c(){
        return 2 * pi * r;
    }
    void set_r(int new_r){
        r = new_r;
    }
};
int main(){
    //通过类创建一个圆
    Circle c1; //圆,对象
    c1.r = 10;
    c1.set_r(5);
    cout << c1.cal_c()<<endl;
    return 0;
}

2.2 内联函数

宏函数:
可以将一个或者多个变量自动替换成一个规定好的表达式,不需要对栈进行操作,提高运行效率和内存空间
宏函数的缺陷:
下面程序输出的结果是410,因为Myadd(10 ,20) * 20在编译器里运行的时候,被编译成10 + 20 * 20
所以要改成# define Myadd(x,y) (x+y)

# define Myadd(x,y)  x+y
void test01()
{
    int ret = Myadd(10, 20) * 20; //预期结果 600
    cout << "ret = " << ret << endl;
}
int main(){
    test01();
    return 0;
}

但是封装好的函数一般就不会出现这种问题,所以提出了内联函数实现相同的功能代替define

inline int Myadd(int x,int y)
{
	return x + y;
}

加上关键字,编译器不一定就按照内联函数执行,只是一个建议,具体情况编译器自己可以判断
内联函数的注意事项(和普通函数的区别)

  1. 不能有循环语句,开销大默认不是内联
  2. 不能有太多条件判断
  3. 不能过于庞大
  4. 不能对函数进行取址(因为内联函数是个表达式替换,没有实际地址)

2.3 函数的默认参数

不传参的情况下,函数自己可以用提前定义好的参数值

void test(int a = 10, double b = 2.24){
...
}

注意事项:
如果有一个位置有了默认参数,那么右边的所有传参都需要有默认参数
void test(int a = 10, int ,b) 这样是不可以的

2.4 函数的占位参数

如果有占位参数,函数调用的时候必须提供这个参数,但是用不到
出现的几率很小

void func(int a , int){}
finc(4, 3)

函数的声明和实现最多只有一个地方有默认参数
像下面这样实现是可以的
void func(int a = 10, int b = 10);
void func(int a, int b){}

2.5 函数的重载

2.5.1 内容

函数名称可以重复,但是参数个数/类型/顺序不同,在同一个作用域中就叫做函数重载。

//以下的函数定义可以同时存在于一个作用域中
void func(){}
void func(int a){}
void func(const int a){} // 因为const开辟临时空间,所以可以这么写
void func(double a){}
void func(double a, int b){}
void func(int a, double b){}
...

但是函数的返回值不能作为函数的重载条件
下面这个情况是不可以的,调用的时候会编译错误

int func(){return 3;}
double func(){return 3.14;}

重载中使用默认参数也会产生二义性问题,下面的两个情况就发生了问题
void func(int a , int b = 10){}
void func(int a){}

2.5.2 重载的原理

在这里插入图片描述

2.6 extern_C

在C++中,函数重载之后,编译器会把这个函数的名称偷偷改变
通过#include调用h文件方法的时候要在程序前面加上
extern “c” void func(); //func是要调用的函数名

#ifdef __cplusplus
extern “C”

解决的问题就是在C++中调用C的代码

2.7 private, public, protected

2.7.1 三者功能

C语言封装的属性和行为分开处理了,导致繁琐并且有可能能产生功能的误用
C++因为支持了结构体内部函数,所以模块化更强,对象和类型之间的关系更紧密

struct和class是一个意思,唯一的不同在于,struct是public,class默认是private
私有权限代表了对应的内容在类的外部不可访问,只能在类的内部调用,子类也不能访问,在前面涉及过
使用pulic :可以将后面的内容变成公共的
protected: 用于保护权限,类内部和子类可以访问,类外部不可以访问
默认的权限是private:(写不写都行,建议把private的内容标注上)

2.7.2 建议将成员属性设置成私有的

私有的属性保护性比较强,虽然不能直接更改,但是可以在类的内部添加Public的方法,通过调用方法来读写成员内部的属性。
而且通过方法修改值,可以在处理过程中添加判断语句等,能够更好地满足对应的业务,防止对数据胡乱更改

三、面向对象设计

3.1 构造函数和析构函数

由编译器自己生成,一开始都是空的
构造函数在构造时候被自动调用,析构函数在清理空间被自动调用
构造函数可以被重构
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 深拷贝,浅拷贝

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>