冒号作用域运算符
int atk = 200;
int main() {
int atk = 100;
cout << "atk = " << atk << endl; // 输出100
// :: 前面啥也没有,就是全局作用域
cout << "atk = " << ::atk << endl; // 输出200
return 0;
}
namespace的使用
作用
- 解决名称冲突问题
- 必须在全局作用域下声明
- 命名空间中可以放函数,变量,类,结构体。。。
- 命名空间可以套用另一个命名空间
- 命名空间是开放的,可以随时往原来的命名空间内放新内容
- 匿名命名空间
- 可以起别名
void test1() {
LOL::GoAtk();
WZ::GoAtk();
}
// 放各种数据
namespace A {
int a = 10;
void func();
struct Person {
};
class Animal{};
namespace B { // 命名空间的嵌套
int m_A = 20;
}
}
void test02() {
cout << "作用域B下的m_A为:" << A::B::m_A << endl;
}
// 会和原来的命名空间合并,并且将内容追加
namespace A {
int m_B = 20;
}
void test03() {
cout << A::m_B << endl;
}
namespace veryLongName {
int m_A = 10;
}
void test04() {
// 起别名
namespace veryShortName = veryLongName;
cout << veryLongName::m_A << endl;
cout << veryShortName::m_A << endl;
}
// 匿名命名空间
// 相当于 static int m_C, static int m_D
namespace {
int m_C = 0;
int m_D = 0;
}
int main() {
// test1();
//test02();
//test03();
test04();
// namespace 用来解决命名冲突的问题
return 0;
}
// 解决名称冲突
// game1.h
namespace LOL {
void Tak();
}
// game1.cpp
void LOL::Tak() {
cout << "LOL" << endl;
}
// game2.h
namespace WZ {
void Tak();
}
// game2.cpp
void WZ::Tak() {
cout << "WZ" << endl;
}
int main() {
cout << LOL::Tak() << endl;
cout << WZ::Tak() << endl;
}
using声明和using编译指令
namespace KingGlory {
int sunwukongID = 10;
}
void test01() {
int sunwukongID = 20;
using KingGlory::sunwukongID;
// using声明,注意避免二义性问题
// 上面的using声明表示要使用KingGlory下的sunwukongID
// 但是就近原则
cout << sunwukongID << endl; // 会报错,多次声明
// cout <<KingGlory::sunwukongID << endl;
// 即使这样也不行
}
namespace LOL {
int sunwukongID = 30;
}
void test02() {
int sunwukongID = 40;
using namespace KingGlory; // 打开KingGlory房间,不一定用
using namespace LOL; // 打开LOL房间,不一定用
cout << sunwukongID << endl;
}
int main() {
test01();
return 0;
}
C++对C语言的增强(对比着看)
- 全局变量的增强
// c语言中,可以编译通过
int a;
int a = 10;
int main() {
printf("%d\n", a);
return 0;
}
// c++语言中,不能编译通过
int a;
int a = 10; // 重定义
int main() {
printf("%d\n", a);
return 0;
}
- 函数检测增强
// c语言
int GetMax(a, b) {
// 只有一个警告,要有返回值
}
void test02() {
GetMax(10, 10, 10); // 啥都没报
}
int main() {
//printf("%d\n", a);
test02();
return 0;
}
// c++
// 函数检测增强,参数类型检测增强,返回值检测增强, 函数调用参数检测增强
int GetMax(int a, int b) {
return (a > b ? a : b);
}
void test02() {
GetMax(10, 10);
}
int main() {
//printf("%d\n", a);
test02();
return 0;
}
类型转换检测增强
// c语言
void test03(){
// 可以编译通过
char* p = malloc(sizeof(64)); // malloc返回值是void*;
}
void test03(){
// 可以编译通过
char* p = (char*)malloc(sizeof(64)); // 必须进行类型转换;
}
struct增强
// C++
struct Person {
int age;
void plusAge(){
age++
}; // C语言中,结构体内不能声明函数,C++可以
}
void test04() {
Person p1;
p1.age = 100;
p1.plusAge();
cout << p1.age << endl;
}
int main() {
test04();
return 0;
}
三目运算符增强
void test05() {
int a = 10;
int b = 20;
cout << "ret = " << (a > b ? a : b) << endl;
(a < b ? a : b) = 100; // C++中返回的是变量
cout << "a = " << a << endl; // 结果是100
cout << "b = " << b << endl;
}
int main() {
test05();
return 0;
}
const增强
const int a = 10;
int* pa = (int*)&a;
*pa = 100;
printf("%d\n%d\n", *pa, a);
// 结果是100,100
// 但是在C++中就不一样了
const int a = 10;
int* pa = (int*)&a;
*pa = 100;
cout << "*pa = " << *pa << endl; // 结果是100
cout << " a = " << a <<end; // 结果是10
// a的值并没有改变
在C++中,const int a = 10
创建了一张键值表,并不会实际开辟内存空间
当执行int* pa = (int*)&a时,操作系统会给pa开辟一块新的空间,空间内存放的值是10,当执行*pa时,操作的是新的空间,而不是对a进行修改
int* pa = (int*)&a;
// 相当于
int tmp = a; // 创建了一个临时空间
int* pa = (int*)&tmp;
// pa操作的是tmp那块空间
所以,如果使用const声明某个变量,并且为这个变量分配内存的话,我们就可以通过指针修改绕过const的限制来修改变量了
int a = 10;
const int b = a; // 分配了内存
int* pb = (int*)&b;
cout << "*pb = " << *pb << endl;
cout << "b = " << b << endl; // 结果都是10
自定义类型也可以分配内存,所以也可以绕过const限制来修改
struct Person {
int age;
string name;
};
int main() {
const Person p1 = { 18, "sb" };
Person* p = (Person*)&p1;
p->age = 10;
p->name = "nb";
cout << p1.age << endl; // 也可以被修改
cout << p1.name << endl; // 可以修改
return 0;
}
内部和外部链接
C语言中,const默认是外部链接,如果一个工程内的两个文件都包含const int a
则会报错,如果要使用,要加上extern
但是在C++中,const默认是内部链接,如果一个工程内的两个文件都包含const int a
就不会报错,如果要使用的话,就要在这两个const声明的变量前都加上extern,用来提升作用域
引用
基本用法
type& 新名字 = 原名
void test01() {
int a = 10;
int& b = a;
b = 100;
cout << "a = " << a << endl; // 结果是100
cout << "b = " << b << endl; // 结果是100
cout << &a << endl;
cout << &b << endl;
// 地址相同
}
引用必须进行初始化
int& ref;
// 报错
引用初始化后的指向不可以修改
void test02() {
int a = 10;
int b = 20;
int& ref1 = a;
int& ref2 = b;
ref1 = ref2;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "ref1 = " << ref1 << endl;
cout << "ref2 = " << ref2 << endl;
cout << "a的地址:" << &a << endl;
cout << "ref1的地址:" << &ref1 << endl;
cout << "b的地址:" << &b << endl;
cout << "ref2的地址:" << &ref2 << endl;
}
ref1初始化的时候指向的是a,
ref2初始化的时候指向的是b,
后面,ref1 = ref2的时候,并没有改变指向,
通过打印地址,可以看到,指向没有改变
对数组的引用
void test03() {
// 数组的引用
// 方式一
typedef int Arry[10]; // 将含有10个整型元素的数组起了一个别名Arry
int arr[10] = { 0 };
Arry& aref = arr;
// int& aref[10] = arr; // 不能直接建立引用
for (int i = 0; i < 10; i++) {
aref[i] = i;
}
for (int i = 0; i < 10; i++) {
cout << aref[i] << " ";
}
cout << endl;
// 方式二
int(&ref2)[10] = arr;
for (int i = 0; i < 10; i++) {
ref2[i] = i;
}
for (int i = 0; i < 10; i++) {
cout << ref2[i] << " ";
}
}
函数中的引用
引用最常见的地方是函数的参数和返回值
函数参数
void MySwap(int& m, int& n) {
int tmp = m;
m = n;
n = tmp;
}
void test04() {
int a = 10;
int b = 20;
MySwap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b <<endl;
}
可见引用是比较方便的,形参不用加'*',实参不用加'&'
引用的本质
本质就是一个指针常量
int a = 10;
int& ref = a;
// 相当于const int* p = &a
// 这也就是为什么一定要进行初始化,并且初始化必须要合法的内存
指针的引用
在C语言中,如果要修改指针的指向,通常可以使用二级指针来修改
但是在C++中就可以通过引用来实现该功能,更简单,明了
struct Person {
int age;
};
void AllocByPtr(Person** pp) {
*pp = (Person*)malloc(sizeof(struct Person));
(*pp)->age = 18;
}
void AllocByRef(Person* &pp) {
pp = (Person*)malloc(sizeof(Person));
pp->age = 10000;
}
void test01() {
Person* p = NULL;
AllocByPtr(&p);
cout << "p->age = " << p->age << endl;
}
void test02() {
Person* p = NULL;
AllocByRef(p);
cout << "p->age = " << p->age << endl;
}
int main() {
// test01();
test02();
return 0;
}
常量的引用
void test01() {
const int& ref = 10; // 相当于 int tmp = 10; int& ref = tmp;
// 分配了内存空间的都可以通过指针来修改
int* pref = (int*)&ref;
*pref = 1000;
cout << "ref = " << ref << endl;
}
// 常量引用的使用场景,用来修饰形参
void ShowValue( const int& ref) {
// ref += 100; // 如果只想展示之而不改动的话,在传递形参的时候就要加上const
cout << "ref = " << ref << endl;
}
void test02() {
int a = 999;
ShowValue(a);
}
int main() {
//test01();
test02();
return 0;
}