//C++兼容绝大多数C语言语法
//C语言的第一个问题是命名冲突,如rand在有头文件<stdlib.h>和没有的时候
#include <iostream>
//是input output stream的缩写,是标准的输入输出流库
namespace wjl
{
int rand = 10;
//可以定义变量、函数、结构体等
struct Node
{
int data;
struct Node* next;
};
//命名空间是可以无限嵌套的
//访问方式:bit::pg::rand
//不同文件的同名命名空间会进行“合并”,当作一个处理
}
//namespace 本质是定义一个域,不同的域可以有相同的命名,相同的与不可以有相同的名
//C++标准库都放在std的命名空间中
//c++的域:函数局部域、全局域、命名空间域、类域
//展开整个命名空间
//using namespace wjl;//为了方便,但项目不推荐
using namespace std;
//展开部分命名空间
//using wjl::rand;//经常访问不存在冲突
//int main()
//{
// printf("%d ", wjl::rand);//::到命名空间去查找
// int a = 1;
// printf("%d ", a);
//
// //struct wjl::Node p1;这里bit在Node前面,因为struct只是一个关键字,不是名字
// //::域作用限定符,若前面没有东西,则默认到全局或局部查找(编译时)
// printf("%d ", ::a);
// return 0;
//}
//int main()
//{
// int a = 0;
// double b = 2.22222222;
// printf("%.2lf", b);
// //cin >> a;
// cout << a << endl;
// //cout是ostream类对象,主要面向窄字符的标准输出流,有自动类型识别
// //cin主要面向窄字符的标准输入流,有自动类型识别
// //endl是一个函数,行为等价于“\n”
// return 0;
//}
//int main()
//{
// //在IO需求比较大的地方,加上一下三行代码,可以提高C++IO效率
// ios_base::sync_with_stdio(false);
// cin.tie(nullptr);
// cout.tie(nullptr);
// return 0;
//}
//缺省参数
void Fun(int a = 10)
{
cout << a << endl;
}
//半缺省必须从左到右连续缺省,不能间隔跳跃
//传几个实参,就给前几个
//缺省定义不能在声明和定义同时给,只能在声明给
//int main()
//{
// Fun();//没有传参数时,使用默认值
// Fun(20);//有传参数时,使用传的值
// return 0;
//}
//函数重载——同一作用域的同名函数
//C++支持重名函数
// 1、参数类型不同,但是同名
// 2、参数个数不同
// 3、参数顺序不同
// 返回类型不能作为重载条件,因为无法进行区分
//引用
// 以前在C语言里,要改变实参,只能传实参地址
// 但是在C++里因为引用的存在,只需要用别名就可以直接传实参,从而代替指针的作用
//指针变量也可以取别名,以代替二级指针的作用
//int main()
//{
// int a = 0;//引用在定义的时候必须初始化
// int& b = a;
// int& c = a;//b和c是a的别名
// int& d = a;//也可以给别名取别名,其实还是相当于a
// //++d;
// cout << &a << endl;
// cout << &b << endl;
// cout << &c << endl;
// cout << &d << endl;
// return 0;
//}
//int& func()
//{
// int a = 0;
// return a;
//}这里就是野指针一样的东西,因为a建立在栈上,用完即销毁,这里返回的引用是野指针一样的东西,编译会给警告
//int main()
//{
// //引用不能改变指向
// int a = 0;
// int& b = a;
// int d = 20;
// b = d;//引用一旦引用实体,就不能再引用其他实体
//
// //将引用作为返回值可以减少拷贝,直接修改,以栈为例
// //cout << a << endl;
//
// //但是引用并不能完全替代指针
// //func();
// return 0;
//}
//const引用的价值
//int main()
//{
// const int a = 10;
// const int& ra = a;
//
// int b = 20;
// const int& rb = b;//表达的意思是
//
// //引用的时候权限可以缩小,但是不能放大
// b = 30;
// //++rb//这里就不能作出更改
// //以上两者权限不一样,但是地址是一样的
//
// int rd = (a + b);//这里(a+b)就是一个临时对象,将它的值拷贝给rd
// const int& rbb = (a + b);//rbb是临时对象的别名
//
// double d = 12.34;
// int i = d;//隐式类型转换——产生一个临时变量存储
// const int& ri = d;//这里d的整型部分会给一个临时对象,而ri是这个临时对象的别名,而临时对象具有常性
// //所以要用const进行类型转换
// double& rd = d;//这里就不用,因为不存在隐式类型转换
//
// //表达式运算的结果、函数传值返回、类型转换是常见的产生临时对象的过程
// return 0;
//}
//引用和指针的区别
// ·语法概念上,引用是取别名不开空间,指针是存储一个变量的地址,需要开辟空间
// ·引用在定义时必须初始化,指针建议初始化,但不是必须
// ·引用在初始化时引用一个对象后,就不能再引用其他对象;而指针可以在不断地改变指向对象
// ·引用可以直接访问指向对象,指针需要解引用才是访问指向对象
// ·sizeof中含义不同,引用结果为引用类型大小,而指针始终是地址空间所占字节个数
// ·指针很容易出现空指针和野指针的问题,引用很少出现,相对安全一些
//内联 inline ——替代宏函数
// 在编译的时候C++编译器会在调用的地方展开内联函数,也就不需要再建立栈帧,可以节省时间
//但是vs编译器debug版本下面默认是不展开inline,为了方便调试
//inline是给编译器的建议,对于递归和大的函数编译器可以选择不展开,进行忽略
//展开是由代价的,假设函数有一百条指令,调用这个函数有一百个位置,若展开会让编译可执行程序非常大
//内联直接放到.h里面,这样方便展开,不要分离到两个文件,内联属性会失效,而且不能编译
//内联适合频繁调用的短小函数
#define add(x,y) ((x) + (y))
//·为什么不能加分号?
// 宏的本质是替代,如果加了分号,预处理以后就会出现有两个分号相连的情况
//·为什么要外面的括号:
// 比如(1+2)*3,若不加括号,替换以后为1 + 2 * 3
//·为什么要加里面的符号?
// 位运算的优先级都很低,比如我传(x&y, x|y)则会变成中间两个先加
//C++ 更加严格,C语言malloc的时候指针类型不转换也可以,因为存在隐式类型转换
//nullptr是一个特殊的关键字,是一种特殊类型的字面常量,可以转换成任意指针类型,
// 但是又不能转换为整型,弥补了C语言过度模糊的定义,因为C语言的NULL定义是0。
//
//类和对象
//class是定义类的关键字,类中不光有数据,还有方法,比如函数
class Stack//类名就是类型
{
protected:
void Push(int x)
{
//...
}
public:
void pop()
{
//...
}
private:
//定义需要开空间,声明只是说有这么个东西,并没有开空间
int* a;
int top;
int capacity;
};
//访问限定符:public private pretected
// 是C++一种实现分装的方式,没有访问限定符类默认是private,struct是public
// C++中也可以用struct定义类
// 访问限定符的作用域从出现开始,到下一个访问限定符或者到类的结束
// 为了区分成员变量,会给成员变量进行特殊标记:如在前面加一个_或者m开头
//
struct ListNode
{
int data;
ListNode* next;
//C语言这里就不可以,但C++的struct已经升级为了类,名称就是类型
};
//C++每个花括号中都是一个新的域——类域
int main()
{
Stack st;
st.pop();
//st.push();这个就是不能访问的
return 0;
}