Day03
一、c++概述
-
面对对象(封装、继承、多态)
-
泛型编程
-
贝尔实验室
......
二、第一个cpp
#include <iostream> //标准输入输出流 类比stdio.h
using namespace std; // 使用 标准 命名空间
int main()
{
// << 左移 在c++中用于在cout后拼接输出内容
// endl __ end line 刷新缓冲区并且换行
cout << "hello world" << 12345 << endl; // 输出并换行
system("pause"); // 阻塞代码
return EXIT_SUCCESS;
}
三、双冒号作用域运算符
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
int atk = 1000;
void test()
{
int atk = 2000;
cout << "atk=" << atk << endl;
//::代表作用域,若前面什么都不添加代表全局作用域
cout << "全局的 atk=" << ::atk << std::endl;
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
四、namespace
1.解决名称冲突
//1.kingGlory ATK
void goAtk()
{
cout << "王者攻击实现" << endl;
}
//2.LOL ATK
void goAtk()
{
cout << "联盟攻击实现" << endl;
}
//3.main
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include "game1.h"
#include "game2.h"
void test()
{
goAtk(); //此时两个goAtk无法判别调用哪一个,重定义报错
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
(1)到.h文件中声明命名空间
#include <iostream>
using namespace std;
namespace kingGlory
{
void goATK();
}
#include <iostream>
using namespace std;
namespace LOL
{
void goATK();
}
(2)到实现处添加函数作用域
#include "game1.h"
void kingGlory::goAtk()
{
cout << "王者攻击实现" << endl;
}
#include "game2.h"
void LOL::goAtk()
{
cout << "联盟攻击实现" << endl;
}
(3)到调用处添加作用域
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
void test()
{
kingGlory::goAtk();
LOL::foAtk();
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
2.命名空间下可以放变量、函数、结构体、类...
// 命名空间下可以放变量、函数、结构体、类...
namespace A
{
int m_A;
void fun();
struct Person{};
class Animal{};
}
3.命名空间必须写在全局作用域下(写在函数内部是不行的)
4.命名空间可嵌套
namespace A
{
int m_A;
void fun();
struct Person{};
class Animal{};
namespace B
{
int m_A;
}
}
//调用 B::C::m_A
5.命名空间是开放的,可以随时追加
namespace A
{
int m_A;
void fun();
struct Person{};
class Animal{};
namespace B
{
int m_A;
}
}
//后续追加,合并而非取代
namespace A
{
char A_char;
}
6.可以是匿名的(相当于是Static,全局)
namespace
{
int m_A;
void fun();
struct Person{};
class Animal{};
}
//直接调用 ::m_A
7.可以起别名
namespace longname
{
...
}
void test()
{
namespace longname = shortname;
cout << shortname :: m_E << endl;
}
五、using声明
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
namespace kingGlory
{
int swk = 1;
}
void test()
{
// using声明
using kingGlory::swk;
// 避免局部变量和命名空间成员重名,否则会出错
cout << swk << endl;
}
void test2()
{
int swk = 3;
using namespace kingGlory; // 会使用就近原则
cout << swk << endl;
}
int main()
{
test();
test2();
system("pause");
return EXIT_SUCCESS;
}
另:多个命名空间,需要指明作用域。
六、c++相对于c的增强
1.全局变量检测增强
2.函数的检测增强(返回值检测、形参类型检测、函数调用参数个数检测)
3.类型转换检测的增强
4.struct增强
(1)允许结构体中出现函数
(2)允许创建结构体变量时不加struct
5.bool类型的扩展(bool flag)
6.三目运算符的增强((a>b?a:b) = 100)
7.const增强
(1)全局const和c语言结论一样
(2)局部直接修改失败,间接修改失败
(3)可以认为是一个常量
(4)const修饰只能在内部使用,是内部链接。加extern可以使用
(5)变量初始化,分配了内存可以修改成功
(6)常用const替换#define
七、引用
1.简单概括作用:起别名
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
void test()
{
int a = 10;
int &b = a; //引用必须初始化,并且初始化后不可改变
b = 100;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
void test2() //对数组直接建立引用
{
int arr[10];
int(&parr)[10] = arr;
for (int i = 0; i < 10; i++)
{
arr[i] = 100 + i;
}
for (int i = 0; i < 10; i++)
{
cout << parr[i] << endl;
}
}
2.语法
类型(与原类型一致) &别名 = 原名
3.参数的传递方式
void mySwap(int &a, int &b) //引用传递,相当于写了int &a = a;指向同一块合法地址
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int a = 10;
int b = 20;
mySwap(a, b);
cout << "a = " << a << "b=" << b << endl;
system("pause");
return EXIT_SUCCESS;
}
4.注意点
(1)必须引用一块合法内存
int &a = 10; //err
(2)不要返回局部变量的引用
(3)当函数的返回值是一个引用的时候,可以将函数调用做左值
5.指针引用
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
struct Person
{
int age;
};
void allocateSpace(struct Person **pp)//二级指针修改
{
*pp = (struct Person *)malloc(sizeof(Person));
(*pp)->age = 10;
}
void test()
{
Person *p = NULL;
allocateSpace(&p);
cout << "P.AGE = " << p->age << endl;
}
void allocateSpace2(Person* &pp)
//此处的Person* &pp;相当于写了 Person* &pp = p,给p取了个别名,但能够指向同一块内存
{
pp = (struct Person *)malloc(sizeof(Person));
pp->age = 20;
}
void test2()
{
Person *p = NULL;
allocateSpace2(p);
cout << "P.AGE = " << p->age << endl;
}
int main()
{
test();
test2();
system("pause");
return EXIT_SUCCESS;
}
6.常量的引用
void show(const int&a) //添加const防止误操作修改
{
//a = 10000; //未加const时,会导致此处修改引起外部修改
cout<<"a = "<< a <<endl;
}
void test()
{
int a = 100;
show(a);
cout<<"aaa = "<<a <<endl;
}
八、函数模板
1.模板不能单独使用,必须指定出T才可以使用
// T代表一个通用的数据类型
template <typename T>
void mySwap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}
void test()
{
int a = 1;
int b = 2;
double m = 1.1;
double n = 2.2;
mySwap(a, b); //需要一致的数据类型 等价 mySwap<int>(a, b);
cout << "a = " << a << ",b = " << b << endl;
mySwap(m, n);
cout << "m = " << m << ",n = " << n << endl;
}
2.例题应用
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
using namespace std;
// 通用函数对char和int数组进行排序 从大到小
template <typename T>
void mySwap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}
template <typename T>
void mySort(T arr[], int len) //选择排序
{
for (int i = 0; i < len; i++)
{
int max = i;
for (int j = i + 1; j < len; j++)
{
if (arr[max] < arr[j])
{
max = j;
}
}
if (i != max)
{
mySwap(arr[i], arr[max]);
}
}
}
template <typename T>
void printArr(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
void test()
{
char charArr[] = "helloworld";
int len = strlen(charArr);
mySort(charArr, len);
printArr(charArr, len);
int intArr[] = {5, 7, 9, 5, 6, 3, 6, 1};
int len2 = sizeof(intArr) / sizeof(int);
mySort(intArr, len2);
printArr(intArr, len2);
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
3.函数模板和普通函数的区别
九、类
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
using namespace std;
// 设计一个类,求圆的周长
const double PI = 3.14;
class Cicle
{
public: //权限
int m_R; //成员变量
double calZC() //成员函数
{
return 2 * m_R * PI;
}
void setR(int r)
{
this->m_R = r;
}
int getR()
{
return this->m_R;
}
};
void test()
{
Cicle c1; //创建对象,实例化
c1.setR(100);
double ret = c1.calZC();
cout << "Cicle's ZC = " << ret << endl;
cout << "Cicle's radius = " << c1.getR() << endl;
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
十、默认参数
1.语法:形参 类型 变量 = 默认值
2.注意:若有一个位置有了默认参数,那么从该位置七,从左往右都必须有默认值
int fun(int a =10,int b = 10)
{
return a+b;
}
3.另:函数的声明和实现,只能有一个提供默认参数,不可以同时添加
4.占位参数(暂无用)
十一、函数重载
1.函数重载的条件:
(1)在同一作用域下
(2)函数的名称要相同
(3)参数的类型、个数、顺序不同。返回类型不同其余相同的情况不允许重载。
void myFun(int &a)
{
cout << "无const调用" << endl;
}
void myFun(const int &a)
{
cout << "const调用" << endl;
}
void funTest()
{
int a = 100; //a可读可写所以会调用无const
myFun(a);
}
2.碰到默认参数也要避免二义性的出现
void fun(int a,int b = 20){};
void fun(int a){};
void test()
{
fun(10); //err
}
十二、extern
让c++的代码也能调用c的代码
1.情景:在c项目的.h中写了重载函数show().在cpp文件中调用这个外部的函数(很少用)
extern "C" void show(); //以c语言的方式链接文件引入show函数
void test()
{
show();
}
2.更常见的是在.h文件中去操作
#ifdef __cplusplus
extern "C"{
#endif
...
#ifdef _cplusplus
}
#endif
#include "test.h" //直接引入
十三、封装
1.struct 和 class的区别
struct | class | |
---|---|---|
默认权限 | 私有权限 | 公有权限 |
2.访问权限
-
public:公共权限 成员、类内、类外
-
private:私有权限 成员、类内 儿子不可以访问私有权限
-
protected:受保护权限 成员、类内 儿子可以访问受保护权限