• 第一章 从C到C++


    1.1 C++的发展历史

    80年代贝尔实验室 本贾尼
    83年 正式命名C++
    87年 GNU制定了C++标准
    92年 微软和IBM分别制定了C++标准
    98年 ANSI ISO 制定了标准 C++98 
    03 ISO C++03 
    11 ISO C++11 C++0x

    编译时注意: 使用c99,则需要指明,gcc *.c -std=c99

    1.2 C与C++的关系

    • C++包含了整个C,C是建立C++的基础
    • C++是强类型的语言,对类型检查更加的严格
    • C++扩展了C:
      • c++提供了面向对象的编程机制
      • 运算符重载
      • 异常处理机制
      • 泛型 模板(STL)

    1.3 第一个C++程序

    include <iostream>
    
    int main()
    {
        std::cout << "Hello C++ !" << std::endl;
        // 输出信息不再使用printf函数,
        // cout 是标准输出流对象,std是标准名字空间
        // << 是插入运算符,表示将其后面的数据插入到其前面的对象中,同时返回其前面的对象
        // 满足后面继续插入的需求
        return 0;
    }
    

    1.3.1 头文件

    标准C++头文件不带.h结尾,头文件在/usr/include/c++/4.6/,可以使用C的头文件
    标准C头文件建议去尾加头的方式去使用,例如:

    #include<stdio.h> --------> #include<cstdio>
    #include<string.h> -------> #include<cstring>
    

    非标准C头文件 该怎么用就怎么用,如:

    #include<pthread.h>
    

    1.3.2 源文件

    源文件建议用.cpp后缀名,也可以是.cc .cxx .c++等

    1.3.3 编译器

    使用g++编译器,如果使用gcc需要加一个链接库 -lstdc++
    如果使用.c文件编写C++代码,则编译用下面的命令:
    gcc -x c++ xx.c -lstdc++
    g++的编译选项和gcc相同:

    		-c   编译
    		-o   输出名
    		-On  优化
    		-S   生成汇编 
    		-E   预处理
    		-I   指定头文件的位置
    		-L   指定库的位置
    		-l   指定库名
    		-std 指定编译标准
    		-g   生成调试信息
    
    

    1.4 命名空间

    1.4.1 定义

    就是把一组逻辑上相关的数据组织到一起的逻辑名

    • 便于模块化
    • 防止命名冲突

    1.4.2 语法

    namespace 空间名
    {
        //数据
        int age;
        void fun(){}
    }
    

    1.4.3 如何使用命名空间

    • 在数据前加命名空间::即可
    • 使用using声明
          using 空间名::数据名;
    • 使用using namespace 指令
          using namespace 空间名

    例子:

    #include <iostream>
    using namespace std;
    
    namespace IBM
    {
        int age = 60;
        double salary = 5555;
        void show();
    }
    namespace IBM
    {
        void show()
        {
            cout << "the age of IBM is " << age << ",the salary is "<< salary
            << endl;
        }
    }
    
    namespace NJUST
    {
        int age = 50;
        double salary = 4444;
        void show()
        {
            cout << "the age of NJUST is " << age << ",the salary is " << salary << endl;
        }
    }
    // using namespace IBM;
    using IBM::show;  // 易错
    int main()
    {
        show();
        NJUST::show();
        return 0;
    }
    
    
    

    1.4.4 无名命名空间

    如果一个数据没有定义在任何命名空间,则这个数据属于无名命名空间

    namespace {
                // 防止跨文件访问
                int age = 23;
        }
    	::数据;
    

    例子:

    #include <iostream>
    using namespace std;
    int g_data = 100;
    
    namespace ns1
    {
    	int g_data = 200;
    	void foo(void)
    	{
    		cout << ::g_data << endl;
    	}
    	//int g_data = 200;
    }
    
    int main()
    {
    	using namespace ns1;
    	foo();
    
    	// cout << g_data << endl;  // error
    	cout << ns1::g_data << endl; // 200
    	cout << ::g_data << endl; // 100
    	return 0;
    }
    

    1.4.5 命名空间嵌套

    #include<iostream>
    using namespace std;
    
    namespace ns1
    {
    	int a = 1;
    	namespace ns2
    	{
    		int a = 2;
    		void show()
    		{
    			cout << a <<endl;
    		}
    		namespace ns3
    		{
    			int a = 3;
    			void show()
    			{
    				cout << "this is ns3!" <<endl;
    			}
    		}
    	}
    }
    
    namespace ns4 = ns1::ns2::ns3;
    int main()
    {
    	ns1::ns2::show();
    	// ns1::ns2::ns3::show();
    	ns4::show();
    	return 0;
    }
    
    

    1.5 c++中的结构 联合 枚举

    1.5.1 结构体

    • 结构体的定义和C中的完全相同
    • C++ 中使用结构体做为类型时,可以省略关键字 struct
    • C++ 中的结构体中是可以定义函数的

    例子

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    /* 定义一个结构体表达 日期 */
    struct Date
    {
    	/* 成员变量 */
    	int year;
    	int month;
    	int day;
    	/* 成员函数 */
    	void show()
    	{
    		printf("%04d-%02d-%02d
    ",year,month,day);
    	}
    };
    
    /* 设计一个函数 可以表现 一个日期变量的数据 */
    void show_date(Date date)
    {
    	printf("%04d-%02d-%02d
    ",date.year,date.month,date.day);  
    }
    
    int main()
    {
    	Date date = {2016,2,4};
    	show_date(date);
    	date.year = 2020;
    	show_date(date);
    	date.show();
    	return 0;
    }
    

    1.5.2 联合体

    • 联合体的定义和C中的完全相同
    • C++ 表达联合这个类型时,可以省略union
    • C++ 中支持匿名联合

    例子

    #include<iostream>
    using namespace std;
    
    int main()
    {
    	
    	union 
    	{
    		char data[4];
    		int x;
    	};
    	/* '0'----> 48 'A'--->65  'a'---->97*/
    	x = 0x31323334;
    	// x = 41424344;    D C B A
    	//小端存储
    	for(int i =0;i<4;i++)
    		cout << data[i] <<" ";
    	// 4 3 2 1
    	return 0;
    }
    

    注:用这个程序可以查看大端字节或者小端字节序。

    1.5.3 枚举类型

    • C++表达枚举类型时可以省略关键字enum
    • 可以把枚举赋值给整数,整数不可以赋值给枚举变量 (C++不允许,这里体现了C++对类型检查的严格)

    枚举的例子:

    #include<iostream>
    using namespace std;
    
    enum Direction
    {
    	D_UP = 3,D_DOWN,D_LEFT,D_RIGHT
    };
    
    
    int main()
    {
    	Direction dire = D_LEFT;
    	int x = dire;
    	cout << x << endl;
    	// dire = 2; // 不能把整数赋值给枚举类型的变量
    	// dire = (Direction)2;
    
    	return 0;
    }
    
    

    1.6 c++中的布尔类型 bool

    • 取值有 false true
    • C语言中需要导入一个头文件 #include<stdbool.h>
    • 定义一个变量,除了下面的四个值之外,结果都是真的
      - 0 '' NULL false
    • 有时候用bool 类型 表达整数 真就是1 假就是0

    1.7 函数重载

    1.7.0 C++中的函数

    • C++中的函数的参数列表严格匹配无参代表没有任何参数,void依然可以用
      int foo(void){}// c++ 可以去掉void
    • C++中不再支持函数的隐式声明调用函数, 必须提前声明或者定义
    • 函数的返回值类型不能省略,main函数除外

    1.7.1 在同一作用域中,函数名相同,参数列表不同的函数,构成重载(overload)关系

    	参数列表不同:参数的个数、类型、顺序
    

    1.7.2 举例

    	使用函数指针,调用重载的函数 
    
    #include <iostream>
    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;
    }
    
    int main()
    {
    	int x = 3;
    	double y  = 4.0;
    	add(x, y);
    	int (*p) (int ,int );
    	p = add;
    	p(2,3);
    	return 0;
    }
    

    1.7.3 函数重载的原理

    • C编译器生成函数调用名时只考虑函数名
    • C++编译器生成函数名时不但考虑函数名,而且考虑参数列表

    1.7.4 解决跨编译器调用的问题

    	extern "C" int getmax(int x,int y);
    

    例子:
    func.c

    #include<stdio.h>
    
    int getmax(int x,int y)
    {
    	printf("getmax is c function!
    ");
    	
    	return x>y?x:y;
    }
    

    extern.cpp

    #include<iostream>
    using namespace std;
    
    // 告诉g++ 编译器 按照C语言编译器生成调用函数名
    
    extern "C" int getmax(int x,int y);
    // 分别用gcc 编译func,g++编译extern.c
    // gcc -c func.c
    // g++ -c extern.c
    // g++ func.o exten.o
    // ./a.out
    
    int main()
    {
    	// _Z6getmaxii
    	getmax(20,30);
    
    	return 0;
    }
    

    1.8 内联函数

    1.8.1 可以把函数的二进制代码直接复制到调用位置

    	这样减少了开栈和清理栈的开销 
    

    1.8.2 如何实现

    		#define GETMAX(X,Y) ((X)>(Y)?(X):(Y))
    
    inline int getmax(int x,int y)
    {
    	return x>y ?x:y;
    }
    

    1.8.3

    	小函数 频率调用 适合内联
    	大函数 稀少调用 不适合内联
    	递归函数 不能内联 
    	inline 只是一种请求 请求成功就按照内联调用 请求不成功 就按照普通函数调用
    

    1.9 参数哑元

    1.9.1 如果一个参数只有类型 没有参数名 则叫哑元

    1.9.2 作用

    	让参数列表匹配更加严格
    	保持函数的向前兼容
    		void encode(int pkey);
    		void decode(int skey);
    		void decode(int ); // 新函数
    	区分函数
    		++ 默认前++;
    		operator++();
    		operator++(int);
    

    1.10 参数的默认值

    1 如果一个函数的参数设定了默认值,则调用这个函数时,这个参数可以不传值,如果对这个参数传入值,则传入的值会改变为这个值
    2 语法

    		// void foo(int a = 1,int b,int c = 0); // error
    

    参数的默认值必须靠右
    函数声明和实现分开时 默认值在声明时指定

    举例:

    	/*	设计一个函数 打印一个整数数组 默认打印整数数组的前5个数据 分割符号默认使用逗号 */
    #include<iostream>
    
    using namespace std;
    
    void print_array(int* a,int n = 5,char c = ',')
    {
    	for(int i=0;i<n;i++)
    	{
    		if(i == (n-1))
    			cout << a[i]<<endl;
    		else
    		{
    			cout << a[i] << c ;
    		}
    	}
    	
    }
    int main()
    {
    	int a[] = {34,23,55,321,54,67,34,45};
    	print_array(a);
    	
    	return 0;
    }
    
    

    c++中的动态内存分配

    	new delete
    	类型 *指针名 = new 类型;
    	int *p = new int ;
    	int *p2 = new int(100);
    	
    	申请多个对象的空间
    	new[]     delete[]
    	类型 *p = new 类型[n] 申请n个
    	定位内存分配
    	int *p = new(data)int[23];
    

    c++中的类型转换运算符

    	static_cast<类型>(变量)
    		在某一个方向上 可以做隐式类型转换
    		int* pi;
    		void* pv = pi;
    	dynamic_cast<类型>(变量)
    		适合具有多态性的父子类之间
    	const_cast<类型>(变量)
    		用来去掉const修饰
    	reinterpret_cast<类型>(变量)
    		重新解释内存 最接近C语言的强制类型转换
    		整数变指针
    		指针变整数
    

    c++之父给c程序员的建议

    	1、尽量少使用宏 const enum(定义常量) 
    	2、用inline代替带参的宏
    	3、用namespace 避免命名冲突
    	4、变量随时用随时定义 以保证变量的初始化
    	5、尽量避免使用强制类型转换 如果要进行强制类型转换 尽量使用
    	6、多用new delete 少使用malloc free 
    	7、少使用c 风格字符串 多使用string 类型;
    	8、逐渐建立面向对象的编程思想
    
  • 相关阅读:
    Pandas数据存取
    Pandas统计分析
    (4)awk读取行的细节
    (3)awk命令行结构和语法结构
    安装新版gawk
    (2)BEGIN和END语句块
    (1)AWK快速入门
    shell读取文件的几种方式
    Docker 部署 elk + filebeat
    Linux之关于用户的几个重要配置文件
  • 原文地址:https://www.cnblogs.com/yanyun888/p/6078693.html
Copyright © 2020-2023  润新知