CPP强弱类型
using namespace std; //优化编译 没有用到的就不包含进来
// 泛型的概念 自动推理数据类型
//CPP类型检测严格 精准 属于强类型
int *p1(p2) //() 初始化
for each (int i in a) //遍历a所有的变量
宽字符本地化
#include<locale>
setlocale(LC_ALL,"zh-cn"); //宽字符本地化
//C++重定向: >重写 >>追加 < <<输入
函数模板
函数重载: 根据参数来识别
函数模板:
template<class T>
T add(T a, T b) {
return a + b;
}
原生函数优先于模板函数 强行调用模板 add<int>(1,2)
调用的时候编译 不调用的时候不编译
函数模板意义: 通用 泛型
模板接口:
template<class T>
void show(T num) {
cout << num << endl;
}
//泛型接口 任何的数据类型 任何指针
template<class T, class F>
void run(T t, F f){
f(t);
}
run("sss", show<const char*>); //接口 严格类型
命名空间
命名空间的扩展: 名称相同 同一个命名空间
命名空间的权限:
using namespace data //使用命名空间 ,放在局部等同于局部变量 放在全局等同于全局变量
命名空间没有私有 ,全部变量,函数都是公有 可以访问
命名空间内部: 内层覆盖外层
// ::num 直接访问全局变量 全局变量不存在就是0
using namespace data //使用命名空间 必须在定义之后
//匿名命名空间等同于全局变量
命名空间深入:
namespace stdrun{
int numl;
}
namespace bb = stdrun; //别名
using stdrun::numl; //单独引用命名空间变量或者函数
一般情况下 函数实现放在命名空间之外 内部放声明
namespace stdfun
{
struct Date
{
int getsub();
};
}
int stdfun::Date::getsub() //命名空间::类型::函数名
{
return a - b;
}
全局变量与局部变量
CPP没有声明与定义的差别
namespace data {
int num = 100;
}
int main()
{
int num = 10;
using namespace data; //局部变量覆盖命名空间
cout << num << endl;
}
int num=100;
void main()
{
int num=20;
{
int num=30;
cout<<num<<endl; //局部覆盖 30
cout<<num<<endl; //全局覆盖 100
}
}
static_extern
extern int x ; //引用外部全局变量
static int a; //作用于当前文件
static int x1 = 100;
namespace{
int x1 = 90;
}
int main()
{
//同一个文件下 ::引用的还是static
//跨文件下 ::一般引用是全局
cout << ::x1<< endl << endl; //100
}
// ::优先级: 当前文件的stataic 再是跨文件的extern
// 匿名结构体等同于全局变量 可以跨文件
// ::可以引用除匿名以外的全局变量 可屏蔽匿名
typeid (关键字)
用于获取数据类型
int b;
cout << typeid(b).name() << endl; //int
cout << typeid(10+1.2).name() << endl; //double
cout << typeid("guoshixian").name() << endl;//char const [11]
int *px;
char*py;
if (strcmp(typeid(px).name, typeid(py).name) == 0){
cout << "==";
}
else{
cout << "!=";
}
可变参数模板
类型一致
#include<cstdarg> //可变参数头文件
template<class T>
T add(int n, T t...) //第一个代表多少个参数 第二个代表多少类型列表
{
cout << typeid(T).name() << endl;
va_list arg_ptr; //开头指针
va_start(arg_ptr, n); //从arg_ptr开始读取n个
T res(0); //初始化为0
for (int i = 0; i < n; i++)
{
res += va_arg(arg_ptr, T);//根据数据类型 取出数据
}
va_end(arg_ptr);//结束读取
return res;
}
int main()
{
cout << add(4, 1, 2, 3, 4) << endl;
cout << add(5, 1, 2, 3, 4,5) << endl;
cout << add(4, 1.1, 2.2, 3.3, 4.4) << endl;
cin.get();
return 0;
}
类型不一致
#include<cstdarg> //可变参数头文件
void show() //空函数结束递归
{
}
//参数类型不一致 个数不确定
template<typename T , typename...Args> //typename...Args可变参数
void show(T t, Args...args)
{
cout << t << endl;
show(args...); //不能省略...
}
int main()
{
show(1,2.1,'a',"ssssss");
cin.get();
return 0;
}
实习printf打印
#include<cstdarg> //可变参数头文件
void show(const char*str) //递归终止
{
}
//参数类型不一致 个数不确定
template<typename T, typename...Args> //typename...Args可变参数
void show(const char*str, T t, Args...args)
{
while (str&&*str) //指针不为空 且字符串没到末尾
{
if (*str=='%'&&*(str+1)!='%')
{
++str; //指针向前移动
cout << t; //打印
show(++str, args...); //继续调用
return; //递归回调时 推出while循环
}
else
{
cout << *str++; //打印当前字符并且跳过一个字符
}
}
}
void main()
{
printf("%d14555555%s%c%%%fXXXX",10,"1234",'0',1234.5);
putchar('\n');
show("%d14555555%s%c%%%fXXXX", 10, "1234", '0', 1234.5);
cin.get();
}
默认参数: 外观模式
函数可以快速调用
省略参数
默认参数从右边开始,参数进栈,从右向左
不默认的参数 都在左边 默认右边
auto
自适应数据类型 自动推理
void main()
{
int a[5] = { 5,2,3,4,5 };
for (auto i : a) //auto i 副本 auto&i 原本
{
i += 1; //并没有改变数组元素原本 改变的是a[i]的副本
cout << i << endl; //6 3 4 5 6
}
cout << endl;
for (auto i : a)
{
cout << i << endl; //5,2,3,4,5
}
for (auto &i : a) //auto i 副本 auto&i 原本
{
i += 1; //auto&i 改变数组元素原本 等价于 a[i]+=1;
cout << i << endl; //6 3 4 5 6
}
cin.get();
}
bool
非0解析为1 , 0解析为0
一个字节大小
decltype 关键字
拷贝类型
template<class T>
void show(T*p)
{
decltype(*p) num(*p); //内存备份
}
void main()
{
int a = 3;
//decltype(a)根据一个变量表达式获取类型 (拷贝类型)
decltype(a) a1[5]{ 0 };
for (auto i : a1)
{
cout << typeid(i).name() << " " << i << endl;
}
cin.get();
}
CPP风格数组
//数组初始化两种方法:
//int a[5]{ 1,2,3,4,5 };
//int *p2(new int[5]{ 1,2,3,4,5 });//CPP正式写法
void main()
{
array<int, 10>myint1{ 1,2,3,4,5,6,7,8,9,10 }; //CPP风格数组
array<int, 10>myint2{ 1,2,3,4,5,6,7,8,9,10 };
array<int, 10>myint3{ 1,2,3,4,5,6,7,8,9,10 };
array< array<int,10> , 3 > myint{ myint1,myint2,myint3}; //CPP风格二维数组
for (auto i: myint)
{
for (auto j : i)
{
cout << j<< " ";
}
cout << endl;
}
cin.get();
}
CPP风格别名
//typedef 只能处理C语言
//typedef run runit; //c风格 不能处理c++独有命名空间 函数模板等 类
//一般情况 原则用using 取代 typedef
typedef double DB; //C风格别名
using DBCPP = double; //CPP风格别名
namespace runit = run; //单独别名命名空间‘
#define INT int //宏
typedef int a[10]; //C风格别名
using intarray = int[10];//CPP风格别名
typedef int(*p)(int a, int b); //函数指针类型
using pfun= int(*)(int a, int b);//CPP风格别名
typedef int(*pa[10])(int a, int b); //函数指针数组类型
using pafun = int(*[10])(int a, int b);//CPP风格别名
//typedef三步骤
//1 定义变量: double DB;
//2 加typedef: typedef double DB;
//3 DB就是double
//using三步骤
//1定义变量: int num;
//2增加using INT=: using INT=int num;
//3去掉变量: using INT=int
#include<functional>
namespace china{
template<class T> using t = T;
template<class T> using tp = T*; //模板指针别名
template<class T>
T show(T t1)
{
t<T> tx(t1); //使用模板别名 必须明确其数据类型
tp<int>tp1(&tx);
cout << tx << " " << tp1 << endl;
return T;
}
}
using std::function; //使用命名空间一部分
using fun = std::ios::fmtflags; //命名空间的类变量或者函数别名
void main()
{
a a1;
cin.get();
}
网友评论