因为工作需求学习C++,内容正在不断更新,内容主要来自于网上的视频课
C++是C的超集
C++在C上添加了面向对象编程和泛型编程的思想
- C++基础
- 一、语法基础
- 1.1 Hello world实现
- 1.1.1 命名空间:
- 1.1.2 阻塞功能
- 1.1.3 面向对象三大特性
- 1.2 双冒号作用域运算符
- 1.3 命名空间的使用
- 1.4 using声明和using编译指令
- 1.5 C++对C语言的增强
- 1.6 尽量用const代替define
- 1.7 引用,意思就是起别名
- 1.7.1 引用的知识点
- 1.7.2 引用的本质
- 1.7.3 指针的引用
- 1.7.4 常量的引用
- 1.8 参数的传递方式
- 二、函数和封装
- 2.1 对象中函数的设计
- 2.2 内联函数
- 2.3 函数的默认参数
- 2.4 函数的占位参数
- 2.5 函数的重载
- 2.5.1 内容
- 2.5.2 重载的原理
- 2.6 extern_C
- 2.7 private, public, protected
- 2.7.1 三者功能
- 2.7.2 建议将成员属性设置成私有的
- 三、面向对象设计
一、语法基础 1.1 Hello world实现 1.1.1 命名空间:
using namespace std; 使用命名空间std,理解:打开一个std的房间,房间里有cout等,打开一次代码就可以一直用 system(“pause”); 让命令窗口保留 在函数里调用全局变量的时候可以使用::[变量名]的方式调用 在game1.h文件中 在game1.cpp文件中 在本文件或者其他文件运行的时候: 二义性: 定义结构体的时候,C++可以简洁一点 C++: bool类型增强 三目运算符增强 C++特有允许情况: C++通过上面的方式可以运行,但是a的值没有被改变,a依旧是10 C语言中const默认是外部链接,C++中默认是内部链接 分配内存情况 所以C++中,const修饰的变量是可以用于初始化数组的,C中则不可以 对于下面的语句,MAX从没被编译器看到过,因为在预处理阶段所有的MAX都被自动替换为1024了,所以相关的报错不会提到MAX,而都是1024 b和a的作用就是等同的了 引用必须初始化 引用初始化之后不可修改 引用在C++内部的实现是一个指针常量 可以有效避免二级指针的使用 值传递 一个简单的求圆周长的程序 宏函数: 但是封装好的函数一般就不会出现这种问题,所以提出了内联函数实现相同的功能代替define 加上关键字,编译器不一定就按照内联函数执行,只是一个建议,具体情况编译器自己可以判断 不传参的情况下,函数自己可以用提前定义好的参数值 注意事项: 如果有占位参数,函数调用的时候必须提供这个参数,但是用不到 void func(int a , int){} 函数的声明和实现最多只有一个地方有默认参数 函数名称可以重复,但是参数个数/类型/顺序不同,在同一个作用域中就叫做函数重载。 但是函数的返回值不能作为函数的重载条件 重载中使用默认参数也会产生二义性问题,下面的两个情况就发生了问题 在C++中,函数重载之后,编译器会把这个函数的名称偷偷改变 #ifdef __cplusplus 解决的问题就是在C++中调用C的代码 C语言封装的属性和行为分开处理了,导致繁琐并且有可能能产生功能的误用 struct和class是一个意思,唯一的不同在于,struct是public,class默认是private 私有的属性保护性比较强,虽然不能直接更改,但是可以在类的内部添加Public的方法,通过调用方法来读写成员内部的属性。
也可以通过std::cout<<“hello world”<
return EXIT_SUCCESS 表示代码成功离开,返回正常退出
1.2 双冒号作用域运算符
把客观对象抽象成类
父子对象
一个接口多种方法
::前面如果有std或者什么范围,就相当于到对应的范围找namespace LOL
{
void goAtk();
}
#include "game1.h"
void LOL::goAtk()
{
cout << "LOL攻击实现" <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都有
namespace {
int C = 0;
int D = 0;
}
namespace veryLong{
int C = 0;
int D = 0;
}
namespace veryshort = veryLong; //即可完成起别名
1.4 using声明和using编译指令
避免如下图的情况
以下代码在C中可以跑通,但是在C++不可以int a;
int a = 10;
以下代码在C中可以跑通,但是在C++不可以(没有参数类型和返回值,参数数量不对)get(10, 10, 10)
int get(w, h){
}
以下代码在C中可以跑通,但是在C++不可以(需要改成char *p = (char *)malloc(sizeof(64));)void test(){
char *p = malloc(sizeof(64)); //malloc返回值是void*
}
C中struct不能加函数,C++中可以(void plusAge()struct Person
{
int Age;
// void plusAge();
}
C:struct Person p;
Person p;
C语言中没有bool类型
C++有
非0的bool类型值都默认转为1
所以不论如何赋值,bool只能存0/1
常见情况:int a = 10;
int b = 20;
c = a > b ? a :b;
// c = 20
int a = 10;
int b = 20;
(a > b ? a : b) = 100;
// a = 10, b = 100, 因为C++的三目运算符返回的是变量(这里是b),C返回的是数值
const int a = 10;
// a = 100; C语言这种方式不可以,不能对const直接改值
// 但是C语言用下面指针的方式依旧可以修改a的值,因为编译器是分配内存的方式定义数据
int *p = (int *)&a;
*p = 200;
// a = 200
因为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 <
const Person p1;
//p1.m_Name = "aaa"; 这种方式不可以改const修饰的结构体
Person *p = (Person*)&p1;
p->m_Name = "元歌";
(*p).m_Age = 18;
//利用如此的两行就可以全部修改出来
define的数没有类型,无法类型检测
const能完全替换define的功能
difine的变量没有作用域,自始而终都存活(虽然可以用#undef MAX 解决)#define MAX 2014
1.7 引用,意思就是起别名
1.7.1 引用的知识点
int &b = a;//引用
int b = &a;//取地址
int &a;这样的代码是不可以的int &b = a;//引用
b = c;//这行不可执行,报错
int arr[10];
int (&pArr)[10] = arr;
int &a = NULL;
int &a = 10; 这两个都是不可以的
1.7.2 引用的本质
(static int a可以解决下面的问题)
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 参数的传递方式
地址传递
引用传递
Public能够让对象的东西可以在外部访问#include
可以将一个或者多个变量自动替换成一个规定好的表达式,不需要对栈进行操作,提高运行效率和内存空间
宏函数的缺陷:
下面程序输出的结果是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;
}
inline int Myadd(int x,int y)
{
return x + y;
}
内联函数的注意事项(和普通函数的区别)
2.3 函数的默认参数
void test(int a = 10, double b = 2.24){
...
}
如果有一个位置有了默认参数,那么右边的所有传参都需要有默认参数
void test(int a = 10, int ,b) 这样是不可以的
出现的几率很小
finc(4, 3)
像下面这样实现是可以的
void func(int a = 10, int b = 10);
void func(int a, int b){}//以下的函数定义可以同时存在于一个作用域中
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){}
通过#include调用h文件方法的时候要在程序前面加上
extern “c” void func(); //func是要调用的函数名
extern “C”
C++因为支持了结构体内部函数,所以模块化更强,对象和类型之间的关系更紧密
私有权限代表了对应的内容在类的外部不可访问,只能在类的内部调用,子类也不能访问,在前面涉及过
使用pulic :可以将后面的内容变成公共的
protected: 用于保护权限,类内部和子类可以访问,类外部不可以访问
默认的权限是private:(写不写都行,建议把private的内容标注上)
而且通过方法修改值,可以在处理过程中添加判断语句等,能够更好地满足对应的业务,防止对数据胡乱更改



