面对过程和面向对象
面向过程:功能分解,自顶向下,逐层细化,程序=数据结构+算法
面向对象:程序=对象+对象+。。。
面向对象的三大特性
封装、继承、多态
C++对C的拓展
:: 作用域运算符
using namespace std;
int atk=1000;
int main(){
int atk=2000;
cout<<atk<<endl;//就近原则
cout<<::atk<<endl;//双冒号作用::前什么都没有是全局变量
}
命名空间
-
解决名称冲突
-
命名空间下,可以存储变量函数结构体类等等
-
命名空间必须声明在全局作用下
-
命名空间可以嵌套命名空间
namespace A{ int a=10; namespace B{ int a=20; } } int main(){ cout<<A::a<<endl; cout<<A::B::a<<endl; }
-
命名空间有开放性,可随时添加新内容
namespace A{ int a=10; } namespace A{ int b=20; } int main(){ cout<<A::a<<endl; cout<<A::b<<endl; }
-
命名空间可以使匿名的
namespace { int a=10; } int main(){ cout<<a<<endl; }
-
命名空间可以起别名
namespace aaaaa{ int a=10; } int main(){ namespace aa=aaaaa; cout<<aa::a<<endl; cout<<aaaaa::a<<endl; }
-
调用时要么用using要么用xxxx::
using namespace LOL;//符合就近原则 using namespace King;//但多个using编译指令不符合就近原则 //cout<<LOL::A; using LOL::A;//不符合就近原则
内存分区
四个区域:不同区域的数据有不同的生命周期
- 代码区
存放二进制代码,在程序运行前编译后就用,生成exe,存放CPU指向的机器指令
特点:共享(每次点击exe只有一份代码), 只读(防止程序意外被修改) - 全局区 全局变量,静态变量和常量
也是运行前,在程序结束后,由操作系统释放int g_a=10; int g_b=10; const int cg_a=10; int main(){ int a=10;//普通局部变量 int b=10; cout<< &a <<endl; cout<< &b <<endl; //0x6ffe1c //0x6ffe18 cout<< &g_a <<endl;//全局变量 cout<< &g_b <<endl; //0x472010 //0x472014 static int s_a=10;//静态变量 static int s_b=10; cout<< &s_a <<endl; cout<< &s_b <<endl; //0x472018 //0x47201c cout<<&"Hello World"<<endl;//字符串常量 //0x488001 cout<<&cg_a<<endl;//全局常量 //0x488010 const int c=10;//局部常量 cout<<&c<<endl; //0x6ffe14 }
-
栈区 编译器自动分配释放
程序运行后,函数参数,局部变量
不要返回局部变量的地址
形参数据也会放在栈区int* func(){ int a=10;//局部变量存放在栈区,在程序执行完后自动释放 return &a; } int main(){ int *p=func(); cout<<*p<<endl; cout<<*p<<endl; } //10(第一次打印正确是因为编译器做了保留) //0
-
堆区 程序员分配和释放
利用new开辟,指针也int * func(){ //int a=10; return new int(10); } int main(){ //在堆区开辟数据 int *p =func(); cout<<*p<<endl; cout<<*p<<endl; //10 10 //指针在栈区,但是指针所指的对象在堆区 }
new操作符
建立和删除
建立数组
int *func(){
int *p=new int(10);
return p;
}
int main(){
//new的基本语法
int *p=func();
cout<<*p<<endl;
cout<<*p<<endl;
//释放堆区数据,delete
delete p;
//cout<<*p<<endl;
//10
//10
//1514000
//在堆区用new开辟一个数组
int *a=new int[10];
for(int i=0;i<10;i++)a[i]=i+100;
for(int i=0;i<10;i++)cout<<a[i]<<endl;
delete[] a;
}
引用
给变量起别名
引用的基本操作
//建立对数组的引用
void test2(){
int arr[5]={1,2,3,4,5};
typedef int(ARRAY_TYPE)[5];
ARRAY_TYPE &pArr = arr;
for(int i=0;i<5;i++)cout<<pArr[i]<<endl;
typedef int(&ARRAY_TYPE2)[5];
ARRAY_TYPE2 pArr = arr;
int(&pArr3)[5]=arr;
}
int main(){
//数据类型 &别名 = 原名
int a=10;
int &b=a;
cout<<a<<" "<<b<<endl;
b=100;
cout<<a<<" "<<b<<endl;
//10 10 100 100
test2();
}
注意事项
- 引用必须要初始化
- 引用一旦初始化就不可以更改
引用做函数参数
void Swap1(int a,int b){
int temp=a;
a=b;
b=temp;
}
//地址传递
void Swap2(int *a,int *b){
int temp=*a;
*a=*b;
*b=temp;
}
//引用
void Swap3(int &a,int &b){
int temp=a;
a=b;
b=temp;
}
int main(){
int a=10,b=20;
Swap1(a,b);//形参改变了,实参没改变
Swap2(&a,&b);//改变了
Swap3(a,b);//改变了
}
引用做函数返回值
//不要返回局部变量的引用
int& test01(){
int a=10;
return a;
}
//函数可以作为左值
int& test02(){
static int a=10;
return a;
}
int main(){
int &ref=test01();
//最好不要这样做,会释放
int &ref2=test02();
//函数可以作为左值
test02 = 1000;//返回了a的引用,所以可以对a赋值
}
引用的本质
引用的本质在c++内部实现是一个指针常量
int main(){
int a=10;
//int* const ref=&a
int &ref=a;
ref = 20;
//内部发现ref是引用 *ref = 20;
}
常量引用
void Showvalue(int &val){
//val=1000;
return val;
}
int main(){
//常量引用
//用来修饰形参,防止误操作
int a=10;
int &ref=a;
//int &ref=10;错误
const int &ref2 = 10;//变为只读,不可修改,编译器内部先有了const int的内存
//如果你不想让a被修改,那么久写一个const
Showvalue(a);
}