本贾尼·斯特劳斯卢普---- “C++之父”
C++98: C++标准获得了国际标准化组织(International Organization for Standardization, ISO)和美国标准化协会(American Nationl Standards Institute, ANSI)的批准。
C++:
- 完全兼容C 语言
- 引入类的概念 ---- 面向对象
- 函数运算符重载、引用、常量
- 继承,多重继承
- 虚函数,多态
- 模板 ---- template
- 标准模板库(Standard Template Library, STL)
- …
一、C++ 的输入输出
我们接触一个语言,写的第一个代码常常是:
#include <iostream>
using namespace std;
int main(void)
{
std::cout << "Hello World!" << std::endl;
return 0;
}
这个程序的执行结果是输出一句话:
Hello World!
我们来分片解释一下这个程序:
- 头文件 < iostream >
了解过C 语言的朋友都知道,C 语言的头文件都带有后缀 .h,但这是 C++ ,C++ 98 之后,< iostream > 和 <iostream.h> 是不一样的,这完全是两个文件,后缀为 .h 的头文件 C++ 标准已经明确提出不支持了。
< iostream > 这个头文件是输入输出流的意思,是一个库。- namespace
表示命名空间关键字,可以用来声明或定义命名空间- using
引入命名空间中的变量- std::cout
标准命名空间的重输出流对象
c: console 控制台- <<
输出操作符,表示将后面的参数内容流入到前面的输出流对象中- std::endl
end line, 换行- std::cin
标准命名空间的重输入流对象
C++ 中对输入和输出没有特别的格式要求
和C 语言是有很大区别的:
// C 语言
#include <stdio.h>
int main(void)
{
int a = 0;
float f= 0.0;
scanf("%d", &a);
scanf("%f", &f);
printf("a = %d\n", a);
printf("f = %f\n", f);
return 0;
}
// C++
#include <iostream>
using namespace std;
int main(void)
{
int a = 0;
float f = 0.0;
std::cin >> a;
std::cin >> f;
std::cout << "a = " << a << std::endl;
std::cout << "f = " << f << std::endl;
std::cin >> a >> f;
std::cout << "a = " << a << " f = " << f << std::endl;
return 0;
}
程序执行结果(编译环境 CentOS 7 ):
看起来貌似也很复杂啊,哈哈哈(一个尴尬又不失礼貌的笑 ?)
二、命名空间
在 C++ 中,变量、函数和类都是大量存在的,这些变量、函数和类都存在于全局命名空间中,会导致很多冲突,在没引入命名空间的概念之前,我们的解决办法是命名变量不重名,可是变量太多,难免重名,引入命名空间之后,我们可以使用命名空间对标识符的名称进行本地化,以避免命名冲突或名字污染。
- 命名空间的定义:
- 命名空间中,可以放全局命名空间中的所有东西:
可以定义变量;
可以定义函数;
可以定义命名空间 ---- 嵌套定义。- 同一工程中允许存在多个相同名称的命名空间。
编译器最后会合成一个命名空间。
所以,同名命名空间的变量不要重名。- 一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
- 对没有名称的命名空间,它的成员只在声明该命名空间的文件中可以访问,访问时不需要加命名空间的名称,对其他文件,该命名空间中的内容不可见。
相当于全局变量!!!
看代码:
#include <iostream>
#include <stdlib.h>
using namespace std;
// 定义命名空间 N1
namespace N1
{
int a = 20; // 变量
int Add(int left, int right) // 函数
{
return left + right;
}
}
// 定义命名空间 N2
namespace N2
{
int a = 30;
int sub(int left, int right)
{
return left - right;
}
// 命名空间嵌套定义
namespace N3
{
int a = 40;
int mul(int left, int right)
{
return left * right;
}
}
}
// 没有名称的命名空间 ---- 就相当于一个全局变量
namespace
{
int a = 50;
int division(int left, int right)
{
if(0 == right)
{
exit(1);
}
return left / right;
}
}
namespace N1
{
int b = 1000;
int mod(int left, int right)
{
return left % right;
}
}
int main(void)
{
int a = 10;
std::cout << "part a = " << a << std::endl; // 局部变量的 a
std::cout << "N1::a = " << N1::a << " " << "N1::Add(10, 20) = " << N1::Add(10, 20) << std::endl;
std::cout << "N2::a = " << N2::a << " " << "N2::sub(10, 20) = " << N2::sub(10, 20) << std::endl;
std::cout << "N2::N3::a = " << N2::N3::a << " " << "N2::N3::mul(10, 20) = " << N2::N3::mul(10, 20) << std::endl;
std::cout << "a = " << a << " " << "division(100, 20) = " << division(100, 20) << std::endl; // 这里 a 打印出来是 10,不是 50,就近原则
std::cout << "N1::b = " << N1::b << " " << "N1::mod(5, 3) = " << N1::mod(5, 3) << std::endl;
return 0;
}
编译运行(编译环境:CentOS 7):
三、缺省参数
- 缺省参数的概念
啥叫缺省参数呢?啥叫缺省参数呢?
见过备胎么?如果没有轮胎,就把备胎换上!!!
C++ 语言中,缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。
- 全缺省参数
一个函数的所有参数都带一个默认值。
#include <iostream>
void test(int a = 1, int b = 2, int c = 3)
{
std::cout << "a = " << a << " ";
std::cout << "b = " << b << " ";
std::cout << "c = " << c << " ";
std::cout << std::endl;
}
int main(void)
{
test();
test(10, 20, 30);
test(10, 20);
test(10);
return 0;
}
编译执行(编译环境:CentOS 7):
- 半缺省参数
只有一部分参数带有默认值
- 带缺省值的参数必须放在参数列表的最后面;
这是强制要求,必须从右往左依次给出。- 缺省参数不能同时在函数声明和定义中出现,只能二者则其一;
为什么呢?我们想这样一种情况,万一声明部分的默认值和定义部分的默认值不一样,怎么办?编译器到底该用哪一个?
建议放在声明部分:下面阐述原因
你是一个大佬啊,你写了一个很牛逼的项目,然后你把它卖了,卖了1个亿,这是一件有利可图的事啊,于是你不打算把项目开源,客户拿到的只是你的头文件和编译之后的动态库,用户在声明部分看不到缺省参数,以为你没有默认值,用户体验就不好,之后,用户不乐意了,我不要了,退钱!!!那事情就严重了啊,所以,放到声明部分挺好!- 缺省值必须是常量或者全局变量。
我们来看段代码:
#include <iostream>
void test(int a, int b, int c = 3)
{
std::cout << "a = " << a << " ";
std::cout << "b = " << b << " ";
std::cout << "c = " << c << " ";
std::cout << std::endl;
}
int main(void)
{
//test();
test(10, 20, 30);
test(10, 20);
//test(10);
return 0;
}
编译运行(编译环境: CentOS 7):
不按规定传参,没有通过编译:
我们屏蔽了刚刚出错的两行代码,通过编译:
- C 语言不支持缺省参数
- 在 C 语言中,函数没有指定参数列表时,默认可以接受任意多个参数
- 在 C++ 中,因为严格的参数类型检测,没有参数列表的函数,默认为 void, 不接受任何参数
我们来测试一把:
先测C语言
#include <stdio.h>
void test()
{}
int main(void)
{
test(1, 2);
return 0;
}
编译(编译环境: CentOS 7)通过,运行也没有问题
再测C++
#include <iostream>
void test()
{}
int main(void)
{
test(1, 2);
return 0;
}
编译运行(编译环境: CentOS 7):
我们看到,编译都没通过!!!
证明C++中,没有参数列表的函数,不接受任何参数
我们再做一个有趣的测试;
测试什么呢?
我们来测试一下,在C语言和C++中,如果函数返回值是 void, 而偏偏返回一个值,编译能通过吗?
我们还是先测 C 语言
#include <stdio.h>
void test()
{
return 0;
}
int main(void)
{
test();
return 0;
}
编译运行(编译环境: CentOS 7):
我们看到,只是报了一个警告,编译通过,执行也通过。
我们再来测试一下C++
#include <iostream>
void test()
{
return 0;
}
int main(void)
{
test();
return 0;
}
编译运行(编译环境: CentOS 7):
我们看到,编译没有通过!!!
得到结论,C++对函数检测更加严格