目录
3.多⽂件中可以定义同名namespace,他们会默认合并到⼀起,就像同⼀个namespace⼀样
参数顺序不同(事实上参数顺序不同和参数类型不同是一样的这里单独拿出来帮助记忆)
1.1 C++发展史
1.2 C++版本更新
1.3 C++学习参考文档
Reference - C++ Reference (cplusplus.com)(非官网界,面设计舒服)
C++ 参考手册 - cppreference.com(官网,中文)
cppreference.com(官网,英文)
1.4 C++的第一个程序
#include<iostream>
using namespace std;
int main()
{
cout << "hello world!!!" << endl;
return 0;
}
这里我们可能看不懂#include<iostream> 和using namespace std;和cout是干什么用的,不用怕学到后面我们就明白了。
2 命名空间
2.1 命名空间的价值
#include <stdio.h>
//#include <stdlib.h>
int rand = 10;
int main()
{
// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”
printf("%d\n", rand);
return 0;
}
我们将#include<stdlib.h>注释掉的时候程序是不报错的,但当我们取消掉注释时就会出现命名冲突
2.2 namespace的定义
#include <stdio.h>
#include <stdlib.h>
namespace xkh
{
int rand = 10;
}
int main()
{
//第一次打印是rand函数的地址
printf("%p\n", rand);
//第二次打印打印的是命名空间xkh中的rand变量
printf("%d\n", xkh::rand);
return 0;
}
::是域作用限定符,用来限定访问内容的出处。
1.命名空间中可以定义变量/函数/类型
#include <stdio.h>
#include <stdlib.h>
namespace xkh
{
int rand = 10;
int Add(int a, int b)
{
return a + b;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
printf("%p\n", xkh::Add);
printf("%d\n", xkh::rand);
struct xkh::Node* phead = NULL;
return 0;
}
2. 命名空间可以嵌套
#include<stdio.h>
//比奇堡的命名空间
namespace biqibao
{
//蟹老板的命名空间
namespace xielaoban
{
int rand = 10;
int Add(int a, int b)
{
return a + b;
}
}
//痞老板的命名空间
namespace pilaoban
{
int rand = 1;
int Add(int a, int b)
{
return (a + b) * 10;
}
}
}
int main()
{
printf("%d\n", biqibao::xielaoban::rand);
printf("%d\n", biqibao::pilaoban::rand);
printf("%d\n", biqibao::xielaoban::Add(1, 2));
printf("%d\n", biqibao::pilaoban::Add(1, 2));
return 0;
}
这样可以有效避免在同一个项目中,不同人之间的命名冲突。
3.多⽂件中可以定义同名namespace,他们会默认合并到⼀起,就像同⼀个namespace⼀样
如下面的多文件:
Stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
namespace xkh
{
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* ps, int n);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
STDataType STTop(ST* ps);
int STSize(ST* ps);
bool STEmpty(ST* ps);
}
Stack.cpp
#include"Stack.h"
namespace xkh
{
void STInit(ST* ps, int n)
{
assert(ps);
ps->a = (STDataType*)malloc(n * sizeof(STDataType));
ps->top = 0;
ps->capacity = n;
}
// 栈顶
void STPush(ST* ps, STDataType x)
{
assert(ps);
// 满了, 扩容
if (ps->top == ps->capacity)
{
printf("扩容\n");
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity
* 2;
STDataType* tmp = (STDataType*)realloc(ps->a,
newcapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//...
}
在两个文件中分别进行栈的定义和声明,都放在了xkh的命名空间中,最后的效果是相当于放在了一个命名空间中。
test.cpp
#include"Stack.h"
typedef struct Stack
{
int a[10];
int top;
}ST;
void STInit(ST * ps) {}
void STPush(ST * ps, int x) {}
int main()
{
// 调⽤全局的
ST st1;
STInit(&st1);
STPush(&st1, 1);
STPush(&st1, 2);
printf("%d\n", sizeof(st1));
// 调⽤bit namespace的
xkh::ST st2;
printf("%d\n", sizeof(st2));
xkh::STInit(&st2,2);
xkh::STPush(&st2, 1);
xkh::STPush(&st2, 2);
return 0;
}
在test.cpp中分别使用了全局的栈和xlh命名空间的栈,他们是完全不同的
运行结果
2.3 命名空间使⽤
#include <stdio.h>
namespace xkh
{
int a = 10;
}
int main()
{
printf("%d", a);
return 0;
}
指定命名空间访问
#include <stdio.h>
namespace xkh
{
int a = 10;
}
int main()
{
printf("%d", xkh::a);
return 0;
}
#include <stdio.h>
namespace xkh
{
int a = 10;
}
using xkh::a;
int main()
{
printf("%d", xkh::a);
return 0;
}
#include <stdio.h>
namespace xkh
{
int a = 10;
}
using namespace xkh;
int main()
{
printf("%d", a);
return 0;
}
3. C++输⼊&输出
#include <iostream>
using namespace std;
int main()
{
int a = 0;
double b = 0.1;
char c = 'x';
cout << a << " " << b << " " << c << endl;
std::cout << a << " " << b << " " << c << std::endl;
return 0;
}
#include <iostream>
using namespace std;
int main()
{
int a = 0;
double b = 0.1;
char c = 'x';
//可以⾃动识别变量的类型
cin >> a;
cin >> b >> c;
cout << a << endl;
cout << b << " " << c << endl;
return 0;
}
相比C语言我们要制定输出输入类型,c++确实更加方便了,后面的运算符重载更是体现了其精妙之处。
4. 缺省参数
#include<iostream>
using namespace std;
void func(int a = 1)
{
cout << a << endl;
}
int main()
{
func();
func(100);
return 0;
}
调用函数不传参时,a的值是1,传参时a的值是10;
全缺省与半缺省
#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
int main()
{
Func1();
Func1(1);
Func1(1, 2);
Func1(1, 2, 3);
Func2(100);
Func2(100, 200);
Func2(100, 200, 300);
return 0;
}
运行结果:
缺省参数有妙用,我们来看下面的一个场景:
在创建栈时我们一般开始时只开辟4个空间,但如果我们已经明确的知道我们要在栈中存1000个元素,如果还是成倍的增加栈的容量会浪费时间,我们可以初始化时就开出1000个空间,我们将前面我们的栈的声明改一下
Stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
namespace xkh
{
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//加了n=4
void STInit(ST* ps, int n=4);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
STDataType STTop(ST* ps);
int STSize(ST* ps);
bool STEmpty(ST* ps);
}
在n后面加上等于4,这样我们在平时时可以忽略掉这个参数,当我们需要时我们再传参数,避免扩容带来的不便。
#include"Stack.h"
using namespace xkh;
int main()
{
ST s1;
STInit(&s1);
// 确定知道要插⼊1000个数据,初始化时⼀把开好,避免扩容
ST s2;
STInit(&s2, 1000);
return 0;
}
5. 函数重载
参数类型不同
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
参数个数不同
//参数个数不同
#include<iostream>
using namespace std;
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
参数顺序不同(事实上参数顺序不同和参数类型不同是一样的这里单独拿出来帮助记忆)
//参数类型顺序不同
#include<iostream>
using namespace std;
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
//返回值不同不能作为重载条件,因为调⽤时也⽆法区分
还有一种全缺省的特殊情况:
// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void f1()
{
cout << "f()" << endl;
}
void f1(int a = 10)
{
cout << "f(int a)" << endl;
}
int main()
{
f1();
return 0;
}
虽然构成函数重载但是无参调用f1()时编译器不知道调用哪个函数,会出现如上的报错,但是如果传参调用时不会报错会调用全缺省函数。
****************************************感谢观看,欢迎指正**********************************************