一起学习 每天进步一点点 以后不用干”烧烤“😊
C++系列连载 建议收藏
目录
C++初识
概述
c++是在c基础上的扩充 c++主要是从c的面向过程的编程思想转换为了面向对象的编程思想和c++的泛型编程
c++界面的设计以及对程序员应用上的方便
面向过程:只关注结果,并不关注是谁完成的 例如:int age = 30;
面向对象:关注是谁完成的这件事; 先有对象在操作 例如:Student zs; zs.age = 30;
泛型编程:在C类中类型都是具体化的,int,char;在C++中提供了泛型编程:T a;
面向对象三大特性
封装:不要直接调用对象的变量,需要使用函数进行封装
继承:子类继承父类的资源:(成员变量,成员函数)
多态:一个接口有多种形态多种方式实现
C++和C语言的不同:
基本输入输出
#include <iostream> //c++标准输入输出库头文件
using namespace std; //命名空间
int main(int argc, char *argv[]) //程序进入函数 main函数
{
int i = 0;
cin>>i; //输入
cout<<"i = "<<i<<endl; //输出
return 0; //返回值
}
作用域
int a = 10;
void test_07()
{
int a = 20; //局部变量
cout<<"a = "<<a<<endl; //20 默认打印局部变量a
cout<<"::a = "<<::a<<endl; //10 访问全局变量需要添加作用域
}
命名空间
命名空间中,用于存储代码的区域;可以解决变量重名的问题;
namespace A { //命名空间
int a = 10; //A作用域下的
}
void test_01()
{
int a = 20;
std::cout<<"a = "<<a<<std::endl; //20 当前作用域下的a
std::cout<<"A:: = "<<A::a<<std::endl; // 10 命名空间里的a
}
命名空间的嵌套
namespace A {
int a = 10; //A作用域下的
}
namespace B {
namespace C {
int a = 30;
}
}
void test_01()
{
int a = 20;
std::cout<<"a = "<<a<<std::endl; //20 当前作用域下的a
std::cout<<"A:: = "<<A::a<<std::endl; // 10 命名空间里的a
std::cout<<"B::C:: = "<<B::C::a<<std::endl; //30 命名空间嵌套里面的a
}
命名空间中可以定义函数
namespace D {
void fun1() //命名空间中,还可以定义函数
{
cout<<"命名空间中的函数"<<endl;
}
}
void test03()
{
//注意:不要把命名空间定义到函数体内,因为i命名空间是全局性的
//namespace E {}
D::fun1();
}
命名空间中的函数声名和实现分离
namespace A {
void fun1(); //命名空间中函数的分离
}
void A::fun1() //在命名空间里的函数 定义需要写上作用域
{
cout<<"fun1函数的实现"<<endl;
}
void test_02()
{
A::fun1(); //调用命名空间函数
}
匿名命名空间的设计--只能在当前文件中使用
namespace { //匿名命名空间
int a = 5; //匿名命名空间 只能在当前文件使用
void func()
{
cout<<"匿名"<<endl;
}
}
void test_07()
{
cout<<a<<endl; //匿名空间的使用等价于全局变量或函数
func(); //匿名空间和全局变量或函数 不可重名
}
重命名命名空间
//重命名命名空间
namespace G {
int a = 10;
}
void test_07()
{
namespace reG = G; //重命名命名空间
cout<<reG::a<<endl;
cout<<G::a<<endl;
}
using的使用
//using 的使用
namespace A {
int a = 10;
int b = 20;
}
void test_07()
{
//using A::a; //using只能指定一个成员
//cout<<a<<endl;
//cout<<b<<endl; //ERROR
using namespace A;
int a = 100;
cout<<"a = "<<a<<endl; //100 就近原则
cout<<"b = "<<b<<endl; //局部变量找不到b 去A命名空间去找
}
类型增强
相比较C,C++有哪些需要注意的应用上的细节
同名全局变量的重复声名问题
int a = 5;
//int a; //ERROR在c中不报错 在c++中重复定义
void test_07()
{
cout<<a<<endl;
}
在C++中不允许出现没有参数类型的参数定义
void func(i) //ERROR 在C++中,函数参数必须加类型
{
cout<<i<<endl;
}
void test_07()
{
func(5);
}
在C++中,使用结构体
使用结构体可以省略struct
struct STU{
int a;
int b;
};
void test_07()
{
STU s; //使用STU直接定义 C中需要使用struct STU s;
s.a = 10;
s.b = 20;
cout<<s.a<<" "<<s.b<<endl;//10 20
}
C++bool型变量
在C++中添加了bool型变量 (true(1) false(0))
bool只占一个字节。
void test_07()
{
bool a = true;
if(a)
{
cout<<"真"<<endl; //真
}
cout<<sizeof(a)<<endl; //1
a = false;
if(!a)
{
cout<<"假"<<endl; //假
}
}
C++三目运算符
C++三目运算符返回的是变量 C中返回的是值 所以 C++中的三目运算可以作为左值
void test_07()
{
int a = 10;
int b = 20;
a>b?a:b =5;
cout<<b<<endl; //5
}
const应用(重要)
定义基本类型
C++中使用const定义基本类型 将变量变为常量 表示不可更改的值(符号常量表)
void test_07()
{
//const int a = 5;
//a = 10; //ERROR a变量为常量 值不可修改
// const int a = 5;
// int *pa = (int *)&a;
// *pa = 10;
// cout<<a<<endl; //5
// cout<<*pa<<endl; //10
int a = 5;
const int b = a;
int *pb = (int *)&b;
*pb = 10;
cout<<b<<endl; //10
cout<<*pb<<endl; //10
}
自定义类型const
自定义类型的const,不会产生符号常量表,指针的值和const定义的值是一样的
自定义包含 枚举 结构体 类类型等
void test_07()
{
const STU s = {1,2};
STU *ps = (STU *)&s;
ps->a = 10;
ps->b = 20;
cout<<s.a<<endl; //10
cout<<s.b<<endl; //20
}
const代替宏
宏的应用有两个问题
1.在预处理阶段就转换 在编译阶段如果出错 就会报转换以后值的错误 不便于查找
例如 #define MAX 1000 如果发现异常 就会报1000错误 无法定位
2.在宏定义里面 弱化了作用域的概念
案例:
namespace A {
//#define MAX 1024 //宏的使用,没有作用域的概念
const int MAX = 1024; //const的使用
}
void test_07()
{
//cout<<A::MAX<<endl; //宏没有作用域 在C++中很少看到宏的应用
cout<<A::MAX<<endl; //const替换宏
}
引用(重要)
引用就是给指定变量取别名。
基本类型的引用
void test_07()
{
int a = 10;
int &b = a;
b = 20;
cout<<a<<endl; //20
int &c = b;
c = 30;
cout<<a<<" "<<b<<" "<<c<<endl; //30 30 30
}
数组取别名
void test_07()
{
int arr[]={1,2,3,4,5};
int (&a)[5] = arr;
for(int i=0;i<5;i++)
{
cout<<a[i]<<endl;
}
}
指针取别名
void test_07()
{
int a = 10;
int *pa = &a;
int *(&ppa) = pa;
*ppa = 100;
cout<<a<<" "<<*pa<<" "<<*ppa<<endl;
}
函数取别名
void func()
{
cout<<"func()函数调用"<<endl;
}
void test_07()
{
void (&pf)() = func;
pf(); //func()函数调用
}
引用传参(重要)
务必将地址传参和引用传参区分开,在C++中尽可能的使用&;因为引用比传地址有很大优势。
引用作为函数的参数优点:
1、实参不用取地址
2、引用(形参)不会另辟空间(不占空间)
3、函数内部 不需要指针解引用
结论:在C++中,能用引用尽量优先使用引用
void my_swap(int &a,int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void test_07()
{
int a = 10,b = 20;
cout<<"a = "<<a<<" b = "<<b<<endl; // 10 20
my_swap(a,b);
cout<<"a = "<<a<<" b = "<<b<<endl; // 20 10
}
返回值引用
注意:局部变量的返回,一定不要使用引用,会出现异常(常常适用于链式编程)
int& func()
{
/* int a = 10;
return a; */ //ERROR 如果返回值返回了局部变量 返回后 函数结束 局部变量销毁
//局部变量的引用就找不到了 发生错误
static int a = 10; //引用可返回静态变量 全局变量等
return a;
}
void test_07()
{
int &b = func();
cout<<b<<endl; //10
}
void test_08()
{
cout<<func()<<endl; //10
func() =20;
cout<<func()<<endl; //20
}
引用中的常引用
常引用 避免使用别名更改本身变量的内容 一般在函数传参中使用
void func(const int &a) //避免函数内更改实参的值
{
//a=20; //ERROR 形参是常引用 不可更改值
cout<<a<<endl;
}
void test_01()
{
// const int &a = 10;
// a = 20; //常量的引用不可更改
int a = 10;
func(a);
}