回顾c++
目录
1. 指针常量和常量指针:
c++判断数据类型
#include <typeinfo>
int main(){
int*p1,p2;
cout<<typeid(p1).name()<<endl;
cout<<typeid(p2).name()<<endl;
}
输出:Pi,i
说明p1是一个指针,p2是int
指针常量:int* const,指针的指向是不可以修改的,但值可以修改
常量指针:const int*,指向可以修改,但指向的值不可以修改
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
/* code */
int a = 10;
int b = 1;
int* p = &a;
int* const p2 = &a; //不能改变指向,p2 = &b报错
const int* p3 = &a; //不能改变指向的值,*p3 = b报错
//int const* p3 = &a; //效果一样
const int* const p4 = &a; //既不能也不能
return 0;
}
所以重点在于const的右侧是什么,如果右侧有*,则说明不能修改值;否则,不能修改指向。
2. 引用:
int &a = b;
a是b的引用,给变量b取别名。a与b完全等价,操作a相当于操作b,a和b的地址相同。
引用必须初始化,且初始化后不可以再改变:
int a = 10;
int &b = a; //必须初始化
int c = 20;
b = c; //代码不报错,但是相当于赋值,而不是更改引用
cout<<a<<endl; //20
cout<<b<<endl; //20
cout<<c<<endl; //20
2.1 引用做函数参数
作用:简化指针
//交换函数
//1.值传递:形参不会修饰实参(a和b最后不会改变)
void swap1(int a, int b)
{
int c = a;
a = b;
b = c;
}
//2.地址传递:a和b最后改变
void swap2(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
//3. 引用传递:
void swap3(int& a, int& b)
{
int c = a;
a = b;
b = c;
}
int main()
{
int a = 10;
int b = 20;
swap3(a, b); //a = 20, b = 10
}
void func(int& ref)
{
ref = 100; //因为ref是引用,转换为*ref = 100
}
int main()
{
int a = 10;
int& ref = a; //给a起别名叫ref,相当于int* const ref = &a
func(a);
cout<<a<<" "<<ref<<endl; //100 100
}
2.2 引用做函数返回值
注意,不要返回局部变量的引用
int& test1()
{
int a = 10; //局部变量,存在于栈区
return a;
}
int main()
{
int &ref = test1();
cout<<ref<<endl; //a的内存已经被释放,所以会报错
}
改正:
int& test2()
{
static int a = 10; //静态变量,存在于全局区
return a;
}
int main()
{
int &ref = test2();
cout<<ref<<endl; //不会报错
}
2.3 引用做函数返回值,函数的调用可以作为左值
int& test2()
{
static int a = 10; //静态变量,存在于全局区
return a;
}
int main()
{
int& ref = test2();
cout<<ref<<endl; //10
test2() = 1000;
cout<<ref<<endl; //1000
}
2.4 引用的本质
指针常量(指针的指向不可以改,指向的值可以改)
int& ref === int* const ref
int& ref = a;
int* const ref = &a;
int main()
{
int a = 10;
int& ref = a; //给a起别名叫ref,相当于int* const ref = &a
ref = 20;
cout<<a<<" "<<ref<<endl; //20 20
}
但是ref必须一直指向a。
2.5 常量引用
修饰形参,防止误操作:用const修饰,防止形参修改实参
int & ref = 10; //报错,必须引用一块合法的内存空间
const int& ref = 10; //不报错,
//加上const之后,编译器将代码修改为int temp = 10; int& ref = temp
但是常量引用只读,不可修改:
const int& ref = 10;
ref = 20; //报错,const之后变为只读,不可修改
下方的操作会导致形参修改实参:
void showValue(int& ref)
{
ref = 1000;
cout<<ref<<endl; //1000
}
int main()
{
int a = 100;
showValue(a);
cout<<a<<endl; //1000
}
改正方法:
void showValue(const int& ref)
{
//ref = 1000; //如果写这行会报错
cout<<ref<<endl; //100
}
int main()
{
int a = 100;
showValue(a);
cout<<a<<endl; //100
}
3. 函数重载:
相同名称的函数可以进行复用。
3.1 要求:
必须在同一个作用域,函数的参数个数/类型/顺序不同(注意与函数返回值无关)
void func()
{
cout<<"func"<<endl;
}
void func(int a)
{
cout<<"myfunc"<<endl;
}
int main()
{
func(); //输出:func
func(2); //输出:myfunc
}
3.2 注意事项:
3.2.1 引用作为函数重载条件:
void func(int& a) //int& a = 10不合法
{
cout<<"func1"<<endl;
}
void func(const int& a) //const int& a = 10合法
{
cout<<"func2"<<endl;
}
//类型不同,可以重载
int main()
{
int a = 10;
func(a); //调用没有const的
func(10); //调用const的
}
因为我们从上面知道,const int& a是一个常量引用,常量引用只读,不可修改。所以如果传入的参数是10(一个常量),则func2会被输出。
3.2.2 函数重载碰到默认参数
void func(int a)
{
cout<<"func"<<endl;
}
void func(int a, int b = 10)
{
cout<<"func2"<<endl;
}
int main()
{
func(10); //报错,因为两个函数都可以被调用
func(10,20); //运行func2
}
4. 静态成员
在成员变量和成员函数前加static关键字
4.1 静态成员变量
4.1.1 特点:
所有对象共享同一份数据
在编译阶段分配内存(全局区)
类内声明,类外初始化(必须初始化,否则报错)
class Person
{
public:
static int m_A;
}
//类外初始化
int Person::m_A = 100;
int main()
{
Person p;
cout<<p.m_A<<endl; //100
Person p2;
p2.m_A = 200;
cout<<p.m_A<<endl; //200
}
4.1.2 静态成员变量两种访问方式:
通过对象访问:p.m_A
通过类名访问:Person::m_A
int main()
{
//通过类名访问
cout<<Person::m_A<<endl;
//通过对象访问
Person p;
cout<<p.m_A<<endl;
}
4.1.3 静态成员变量访问权限
静态成员变量也是有访问权限的,如果是私有静态成员变量,同样不能直接类外访问
class Person
{
private:
//所有对象共享同一份
static int m_A;
};
int Person::m_A = 10;
int main()
{
//通过类名访问
cout<<Person::m_A<<endl; //报错inaccesible
}
4.2 静态成员函数
4.2.1 特点:
-
所有对象共享同一个函数
-
只能访问静态成员变量
-
也有两种访问方式:可以通过对象或者通过类名访问
-
静态成员函数也有访问权限(类外访问不到private的成员函数)
class Person
{
public:
static void func()
{
m_A = 100;
//m_B = 200; //报错,静态成员函数只能访问静态成员变量
cout<<"static void func"<<endl;
}
static int m_A;
int m_B; //非静态成员变量
//静态成员函数也有访问权限
private:
static void func2()
{
cout<<"func2"<<endl;
}
};
int Person::m_A = 0;
int main()
{
//通过对象访问
Person p;
p.func();
//通过类名访问
Person::func();
Person::func2(); //报错,静态成员函数不能类外调用
}