【C++】day01 - 【命名空间】【结构、联合、枚举】【布尔】【函数与函数重载】

一、C++发展的历史

80年代 贝尔实验室 本贾尼
83年 正式命名为C++
87年 GNU制定了C++标准
92年 微软和IBM分别指定了C++标准
98年 ansi ISO制定了C++标准(C++编译器默认C++98)
03年 ISO C++03
11年 ISO C++0x

无论C++是否出现新标准,其实对程序员的影响不大,因为C++编译器默认C++98。

使用各标准的方法:
gcc ***.c -std = c99(这是C语言使用c99标准的方法,同样C++也是用这个语句)

二、 C和C++的关系

C++包含整个了C,C是建立C++的基础;
C++对类型检查更加严格;
C++扩展了C:
	C++提供了面向对象的编程机制(以类的方式组织代码)
	运算符重载(一种函数的特殊表现形式)
	异常处理机制(新的错误处理方式)
	泛型 和 模板(STL) (类型通用编程)

三、第一个C++程序

3.1 头文件

#include <iostream>//相当于C中的stdio.h
using namespace std;

int main(){
    
    
	cout << "hallo c++!" << endl;//endl相当于C中的换行符; << 输出的意思
	cout << "请输入年龄" << endl;
	int age = 0;
	cin >> age;// >> 输入的意思
	cout << "你输入的年龄是" << age << endl;
}

选编译器:
方法一:
gcc "文件名" -lstdc++(-lstdc++的意思是添加一个标准C++库)
方法二:
g++ "文件名"

标准C++头文件不再以.h结尾
标准c++头文件在usr/include/c++/4.6/
	如:#include <iostream>
c++可以使用c语言的头文件
	使用标准c头文件,建议去尾加头的方式去使用
		如:#include <stdio.h>  --->  #include <cstdio>
			#include <string.h> --->  #include <cstring>
	使用非标准c头文件
		如Unix的:#include <pthread.h>

3.2源文件

建议使用.cpp结尾
但也可以是.c .C .cc .c++ .cxx

3.3输入输出

使用#include <iostream>
	cout <<
	cin >>
特点是自动处理格式
	如C语言中输入:
		scanf("%d",&age);
	而c++输入:
	cin >> age;	

3.4编译器

建议使用g++
如果使用gcc,则需要加一个链接库 -lstdc++

g++的编译选项和gcc相同
	-c  编译
	-o  输出名
	-On 优化(n是数字)
	-S	生成汇编
	-E  预处理
	-I	指定头文件的位置
	-L	指定库的位置
	-l  指定库名
	-std 指定编译标准
	-g	生成调试信息

3.5 using namespace std;

使用标准的命名(名字)空间 std

四、命名空间

4.1命名空间就是把一组逻辑上相关的数据组织到一起的逻辑名。
	作用是:
		便于模块化
		防止命名冲突
4.2语法
	namespace 空间名{
		//数据
		int age;
		void doo(){
			
		}
	}//注:无分号
4.3如何使用命名空间
	方法一:在数据前加命名空间名::即可
	方法一程序举例:
#include <iostream>
using namespace std;

namespace IBM{
    
    
	int age = 99;
	double salary = 8866;
	void show(){
    
    
		cout << "IBM age is" << age << endl;
	}
}

namespace tarena{
    
    
	int age = 14;
	void show(){
    
    
		cout << "tarena age is" << age << endl;
	}
}

int main(){
    
    


	IBM::show();//调用IBM中的show()

	//改变IBM的age的值,并调用IBM中的show()
	IBM::age = 88;
	IBM::show();
	
	tarena::age++;
	tarena::show();
	
}
你会发现,方法一每次都得使用IBM::,太长了,很麻烦。我们来看方法二
	方法二:使用using声明
				using空间名::数据名;
	方法二程序举例:
#include <iostream>
using namespace std;

namespace IBM{
    
    
	int age = 99;
	double salary = 8866;
	void show(){
    
    
		cout << "IBM age is" << age << endl;
	}
}

namespace tarena{
    
    
	int age = 14;
	void show(){
    
    
		cout << "tarena age is" << age << endl;
	}
}
using IBM::age;//作用是把IBM::age简化为了age
using IBM::show;//作用是把IBM::show简化为了show
int main(){
    
    
	age = 52;//代表的是IBM::age = 52;
	show();//代表的是IBM::show();
	tarena::show();/*注意,因为tarena和IBM的show()函数名一样,因此
					不可以再使用方法二的using tarena::show;了。
					
					因此,当两个空间中的两个变量名(或函数名)一样
					的话(如tarena和IBM的show()函数名以及age一样)
					,还是建议你使用方法一。
					方法二的优点就是,把IBM::age简化为了age
					*/
	
}	
	方法三:
		using namespace 指令
			using namespace 空间名;
		程序举例:
#include <iostream>
using namespace std;

namespace IBM{
    
    
	int age = 99;
	double salary = 8866;
	void show(){
    
    
		cout << "IBM age is" << age << endl;
	}
}

namespace tarena{
    
    
	int age = 14;
	void show(){
    
    
		cout << "tarena age is" << age << endl;
	}
}

using namespace IBM;/*作用是,在以下的作用域,可以直接
						使用age、show()、salary
						
					注意,这时如果你再 同时 使用using namespace tarena;
					那么使用age/show时会报错,因为tarena和IBM的
					age/show名一样。当然,使用salary时是没事的
					*/
int main(){
    
    
	age = 11;
	salary = 9988;
	show();
	
}
	看到方法三,你就明白了using namespace std的作用:
		即在命名空间std的作用域中,cout、cin、endl等就可以使用了。
	从这里你也能看出方法三的好处,否则你在程序前面没有using namespace std
	这一句话时,你每次使用cout时都得用std::cout。很麻烦

综上,三种方法各有长处,用什么方法取决于具体情况。第一种方法是最
不容易出错的。

4.4 无名命名空间

如果一个数据没有定义在任何命名空间,则这个数据属于无名命名空间
第一种无名命名空间:一个全局变量是无名命名空间。
第二种无名命名空间:
	namespace {
		int b = 100;
	}
	也是无名命名空间,只是这种空间里的变量只能在本文件使用,相
	当于C语言中的static的作用。
程序举例:
#include <iostream>
using namespace std;

int a = 99;
namespace {
    
    
	int b = 100;
}
int main(){
    
    
	cout << a << endl;
	cout << b << endl;

	//上面的写法固然对,但更规范的是下面的写法
	cout << ::a << endl;
	cout << ::b << endl;
}

4.5 命名空间嵌套

#include <iostream>
using namespace std;

namespace ns1{
    
    
	int a = 1;
	namespace ns2{
    
    
		int a = 2;
		void show(){
    
    
			cout << a << endl;
		}
		namespace ns3{
    
    
			void show(){
    
    
				cout << "this is ns3" << endl;
			}
		}
	}
}
namespace ns4=ns1::ns2::ns3;
int main(){
    
    
	ns1::ns2::show();//调用ns2下的show,输出 2

	//ns1::ns2::ns3::show();显然,这样写太长了,我们用换一种简单的方式:
	ns4::show();
	
}

4.6 命名空间重命名

	4.5已经讲过了,即namespace ns4=ns1::ns2::ns3;

五、C++中的结构、联合、枚举

5.1结构体

	结构体的定义和C中的完全相同
	不同的是:C++中使用结构体作为类型时,可以省略关键
		字struct,当然也可以不省略。
	不同的是:C++中的结构体是可以定义函数的(C中只是
		可以定义函数指针)。
	程序举例一:
#include <iostream>
#include <cstdio>
using namespace std;

/*定义一个结构体表达日期*/
struct Data{
    
    
	int day;
	int month;
	int year;
	
};//是有分号的


/*设计一个函数,可以表示日期的变量的数据*/
void showData(Data data){
    
    
	//我们暂且用C中的printf函数(cout格式输出我们还没学)
	printf("%4d-%02d-%02d\n",data.year,data.month,data.day);
}
int main(){
    
    
	Data data = {
    
    4,6,2012};
	data.year = 2020;
	showData(data);
	
}
	但是,C++可以在结构体中定义函数,因此我们可以把上例改为下:
#include <iostream>
#include <cstdio>
using namespace std;

/*定义一个结构体表达日期*/
struct Data{
    
    
	int day;
	int month;
	int year;
	void show(){
    
    
		printf("%4d-%02d-%02d\n",year,month,day);
	}
	
};//是有分号的


/*设计一个函数,可以表示日期的变量的数据*/
void showData(Data data){
    
    
	//我们暂且用C中的printf函数(cout格式输出我们还没学)
	printf("%4d-%02d-%02d\n",data.year,data.month,data.day);
}
int main(){
    
    
	Data data = {
    
    4,6,2012};
	data.year = 2020;
	showData(data);

	data.show();
	
}

5.2联合体

	联合体定义  和 C中完全相同
	C++表达这个类型时,可以省略union
	c++中支持匿名联合
	程序举例:
#include <iostream>
using namespace std;

int main(){
    
    
	union {
    
    
	/*这里故意让data与x占的字节数一样*/
		char data[4];
		int x;
	};
	
	/*16进制的31是十进制的49,即ASCII的数字1*/
	x = 0x31323334;
	for(int i = 0; i<4; i++){
    
    
		cout << data[i] << " ";
	}
	cout << endl;
}
		上例值得你注意的是,打印的结果是4321而不是1234,
		这是因为在你的系统上编译时0x31323334按照从右往左
		的顺序排的(即小字节序)

5.3枚举类型

	枚举定义和C语言一样
	C++表达枚举类型时,可以省略关键字enum
	可以把枚举赋值给整数;
	可以把枚举赋值给整数,但整数不可以赋值给枚举(C可以)
		(这里体现了C++对类型检查的严格)
	举例程序:
#include <iostream>
using namespace std;

enum Direcction{
    
    D_UP,D_DOWN,D_LEFT,D_RIGHT};
/*注意:第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。我们在这个实例中把第一个枚举成员的值定义为 1,
第二个就为 2,以此类推。
当然你也可以在这里直接改变其值(后一元素在前一元素加一),比如:
enum Direcction{D_UP,D_DOWN = 88,D_LEFT,D_RIGHT};
则D_UP为0,D_DOWN为88,D_LEFT为89,D_RIGHT为90
*/

int main(){
    
    
	Direcction dire = D_LEFT;
	//dire = 2;C++中这句话是错的,不可以向枚举赋值整数。体现了C++的强类型
	int x = dire;
	cout << x << endl;//输出X的值的2
}

六、C++中的布尔人类型 bool

取值有true和false
C中需要导入一个头文件叫#include <stdbool.h>,而C++不用
	导入这个头文件

定义一个变量,除下面的四个值之外,布尔都是真:
	0  '\0'  NULL  false
有时候用bool类型表达整数,真就是1,假就是0
举例程序:
#include <iostream>
using namespace std;

int main(){
    
    
	bool flag = true;
	/*用法一:用布尔做判断*/
	if(flag){
    
    
		cout << "flag is true" << endl;
	}
	else{
    
    
		cout << "flag is flase" << endl;
	}

	/*用法二:用布尔做整数运算*/
	int x = 1;
	x = x + flag;//即x = 2
	cout << x << endl;
	
	/*输出布尔值*/
	cout << flag << endl;//输出1
	cout << boolalpha << flag << endl;//输出true 
}

七、c++中的符号替换(不用会,没用)

if(a && b){	
}
if(a and b){
}
这两种写法是一样的
各种符号替换如下图所示:

之所以有符号替换这个麻烦的东西,是因为早期欧洲人键盘
	没有|{等符号。
	因此,不建议用c++的符号替换,很麻烦。

八、c++中的函数

8.1c++中函数的参数列表严格匹配,无参代表没有任何参数,void依然可用。
	c中函数无参:int foo(void){}
	c++中无参:int foo(){}
8.2c++中不再支持函数的隐式声明,调用函数必须前置声明或者定义
	程序举例:
#include <iostream>
using namespace std;
void show();//c++中,被调用函数如果定义在了调用函数的后面,就得先声明此函数
int main(){
    
    

	show();
	//show(1);这样写是错的,因为在c++中,你的show()既然定义为无参,则不可以有参

}
void show(){
    
    

}
8.3C++函数的返回值 类型 不能省略,如:
	int show(){
		double a = 10;
	}
	中的int不能省略

九、c++中的函数重载

9.1函数重载概念

	在同一作用域中 函数名相同,而参数列表不同 的函数,构成重载(overload)关系。
	参数列表不同:参数的个数、类型、顺序不同

9.2函数重载程序举例:

	(调用函数重载、使用函数指针)
#include <iostream>
#include <cstdio>
using namespace std;

int add(int x,int y){
    
    
	cout << "add(int,int)" << endl;
	return x + y;
}
double add(int x,double y){
    
    
	cout << "add(int,double)" << endl;
	return x + y;
}
double add(double x,double y){
    
    
	cout << "add(double,double)" << endl;
	return x + y;
}

 
int main(){
    
    
	add(1,1);//打印字符字样:add(int,int)
	add(1,1.5);//打印字符字样:add(int,double)
	add(1.5,1.5);//打印字符字样:add(double,double
	cout << add(1,1) << endl;//打印2

	/*一个小任务:定义一个函数指针,调用第二个add()*/
	/*方法是把该函数的声明抄写来,把函数名add改成(*padd)*/
	double (*padd)(int x,double y);
	padd = add;/*这里注意,虽然有三个add(),但是指针padd会
						自动地选取合适的(即第二个add())*/
	double t = 0;
	double m = 0;
	t = padd(100,12.5);
	m = (*padd)(100,12.5);
	printf("t = %f,i = %f\n",t,m);/*t = 112.500000,i = 112.500000
							即说明,padd(100,12.5)与
							(*padd)(100,12.5)是一样的效果*/
	
}

9.3函数重载的原理

	C语言编译器生成函数调用名时,只考虑函数名;
	C++编译生成调用函数名时,不但考虑函数名,而且考虑参数列表
	下图,左面是C++编译的函数名,右面是C语言的:

在这里插入图片描述

9.4跨编译器调用

	通过9.3也知道了,C++和C通过编译生成的函数名是不同的。
	我们写一个例子,即.c文件的函数可以被.cpp文件调用
	先写一个.c文件:
#include <stdio.h>
int getmax(int x, int y){
    
    
	printf("getmax is c function\n");
	return x>y?x:y;
}
		再写一个.cpp文件
#include <iostream>
using namespace std;

extern "C" int getmax(int x, int y);/*加的extern "C"是为了
									C++可以调用C中的getmax*/
int main(){
    
    
	getmax(1, 2);/*在C++中,getmax的汇编为_Zgetmaxii,而C的
				getmax会变为getmax,因此要在声明中加extern "C",
				从而把C++中的_Zgetmaxii改为getmax*/
	
}
然后.c文件和.cpp文件都编译为.o文件,然后链接为a.out,运行a.out发现可以调用
getmax()。

猜你喜欢

转载自blog.csdn.net/weixin_45519751/article/details/108011568