当前位置 博文首页 >  落禅的博客:一篇文章带你初识C++

     落禅的博客:一篇文章带你初识C++

    作者:[db:作者] 时间:2021-09-10 22:37

    1.命名空间

    关键字:namespace

    在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作 用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字
    污染,namespace关键字的出现就是针对这种问题的。

    命名空间的定义

    定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名 空间的成员。

    //1. 普通的命名空间
    namespace N1 // N1为命名空间的名称
    {
     // 命名空间中的内容,既可以定义变量,也可以定义函数
     	int a;
    	 int Add(int left, int right)
     	{
    		 return left + right;
     	}
    }
    //2. 命名空间可以嵌套
    namespace N2
    {
     	int a;
     	int b;
     	int Add(int left, int right)
     	{
     		return left + right;
     	}
     
     namespace N3
     {
    	int c;
     	int d;
     	int Sub(int left, int right)
     	{
     		return left - right;
     	}
     	
    }
    //3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
    namespace N1
    {
     	int Mul(int left, int right)
      	{
     		return left * right;
     	}
    }
    
    

    命名空间的使用

    命名空间的使用有三种方式:
    加命名空间名称及作用域限定符
    使用using将命名空间中成员引入
    使用using namespace

    //1.使用命名空间名称及作用域限定符
    int main()
    {
    	 printf("%d\n", N::a);
     	 return 0; 
    }
    //2.使用using将命名空间中成员引入
    using N::b;
    int main()
    {
     	printf("%d\n", N::a);
     	printf("%d\n", b);
     	return 0; 
    }
    //3.使用using namespace 
    using namespce N;
    int main()
    { 
    	printf("%d\n", N::a); 
    	printf("%d\n", b); 
    	Add(10, 20);
        return 0;
     }
    

    在C++中我们开头总是写using namespace std; 很多人压根不知道这句话的意思,这里的std就是命名空间,当然这句话的意思就是使用标准命名空间

    2.函数缺省

    缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。

    缺省参数分类:
    全缺省参数
    半缺省参数

    //1.全缺省参数
    void TestFunc(int a = 10, int b = 20, int c = 30)
    {
     	cout<<"a = "<<a<<endl;
    	cout<<"b = "<<b<<endl;
    	cout<<"c = "<<c<<endl;
    }
    //2.半缺省参数
    void TestFunc(int a, int b = 10, int c = 20)
    {
    	 cout<<"a = "<<a<<endl;
    	 cout<<"b = "<<b<<endl;
     	cout<<"c = "<<c<<endl;
     }
    

    注意:

    1. 半缺省参数必须从右往左依次来给出,不能间隔着给
    2. 缺省参数不能在函数声明和定义中同时出现
    3. 缺省值必须是常量或者全局变量
    4. C语言不支持(编译器不支持)

    3 .函数重载

    函数重载:即在C++中容许有同名的函数 函数重载的条件:函数的参数类型不同,返回值不同 注:函数的返回值不能构成函数重载的条件

    #include<iostream>
    using namespace std;
    void Print(int a)
    {
    	cout << a << endl;
    }
    void Print(double a)
    {
    	cout << a << endl;
    }
    int main()
    {
    	Print(1.0);
    	Print(1);
    	return 0;
    }
    

    如上述例子所述,我们要实现两个自定义打印函数,一个打印整数,一个打印浮点数,两个函数列表的参数类型不同
    而函数名却相同,但是我们在编译时却不会报错,这就是函数重载,让我们实现了打印两个不同类型打印函数
    而在C语言中我们就要起两个函数名来实现这件事,如Print_int,Print_double
    那么为什么会出现函数重载这件事呢,这就要从编译链接的过程开始说起:
    1.预处理:头文件的展开+宏替换+去掉注释+条件编译
    2.编译:检查语法,将代码转化成汇编代码
    3.汇编:汇编代码转化为二进制的机器码
    4.链接:将所有文件连接在一起,生成可执行程序 而C++在编译过程中有函数名修饰规则:函数的返回值+函数名+函数参数类型,这样每个函数就能够进行独立识别,既不会产生命名冲突,如下所示:

    
    #include<iostream>
    void  print(int a)
    {
    	cout << a << endl;
    }
    void print(string str)
    {
    	cout << str << endl;
    }
    using namespace std;
    int main()
    {
    	print(1);
    	print("hello  world");
    }
    

    将上述代码在Linux下利用g++编译之后,我们会产生下述结果:

    Print(int a)

    这里我们会发现void print(int a)在这里变成了_Z5printi

    void Print(string str)

    而void print(string str)在这里变成了_Z5printSs
    我们来对比一下:
    从void print(inta)—>_Z5printi;
    而void printf(string str)—>_Z5printSs;
    前面_Z5我们也许不认识,但是看到print我们应该能够联想到这是我们定义的函数名,那么后面的i我们也就可以去联想到知识函数的参数类型,i代表int,Ss代表string,那么我们就可以大胆的猜测_Z5就是前面的函数的返回值类型,这样每一个函数在编译之后:就会形成:
    函数返回值+函数名+参数列表类型
    这将成为为函数唯一修饰,这样看似两个相同的函数就会被特定的区别开来,也就出现了函数重载现象
    而在C语言中,我们将下面代码在Linux gcc下编译之后:

    #include<iostream>
    using namespace std;
    int Ad(int a, int b)
    {
    	return a + b;
    }
    void func(int a,  double b, int* p)
    {
    
    }
    int main()
    {
    
    	return 0;
    }
    

    在这里插入图片描述

    并没有出现像上面C++中那样有函数名修饰规则,而是直接就写了函数名,这样要是出现两个相同的函数名他就无法进行区分,则会报错,这也就解释了为什么C++支持函数重载,而C语言不支持函数重载,总而言之就是二者的函数名修饰规则不同

    4.引用

    简单来说就是给一个变量起别名 引用不是重新写一个变量,而是给一个变量起别名,他和他引用的变量共同访问一块内存空间
    基本语法:数据类型 &别名 = 原名
    例如 int a=10;
    int &b=a;

    在这里插入图片描述

    如上图所示,我们给变量a起别名为b,此时变量a和b就能共同访问这块内存空间,此时我们改变b的值为100,我们会发现a的值也会变为100,这就是最基础的引用
    .引用的注意事项: 引用必须初始化 引用在初始化后不可以改变

    引用的作用

    1.引用做函数参数
    作用:函数传参时,可以利用引用的技术让形参修饰实参
    实例:

    #include<iostream>
    using namespace std;
    //交换函数
    //1.址传递
    void swap1(int a, int b)
    {
    	int temp = a;
    	a = b;
    	b = temp;
    	cout << "swap1 a=" << a << endl;
    	cout << "swap2 b=" << b << endl;
    }
    //2.地址传递
    void swap2(int* a, int* b)
    {
    	int temp = *a;
    	*a = *b;
    	*b = temp;
    }
    //3.引用传递
    void swap3(int& a, int& b)
    {
    	int temp = a;
    	a = b;
    	b = temp;
    }
    int main()
    {
    	int a = 10;
    	int b = 20;
    	//swap1(a, b);//值传递形参不会改变实参
    	//swap2(&a, &b);//地址传递形参会改变实参
    	swap3(a, b);//引用传递形参也会修饰实参
    	cout << "a=" << a << endl;
    	cout << "b=" << b << endl;
    	system("pause");
    	return 0;
    }
    总结:引用的效果和地址传递效果是一样的,引用语法更加清楚简单
    

    2.引用做函数返回值
    作用:引用是可以做函数返回值存在的
    注意:不要返回局部变量引用
    实例:

    #include<iostream>
    using namespace std;
    //引用做函数返回值
    //1.不要返回局部变量的引用
    int& test01()
    {
    	int a = 10;//局部变量在栈区中
    	return a;
    }
    //2.函数的调用可以作为左值
    int& test02()
    {
    	static int a = 10;//全局变量程序运行完后由系统自动释放
    	return a;
    }
    int main()
    {
    	int &ret=test01();
    	cout << ret << endl;//第一次正确,编译器做了保留,
    	cout << ret << endl;//第二次错误,因为a的内存已经释放
    	int& ref = test02();
    	cout << "ref=" << ref << endl;
    	cout << "ref=" << ref << endl;
    	test02() = 1000;///如果函数返回值是引用,这个函数调用可以作为左值
    	cout << "ref=" << ref << endl;
    	system("pause");
    	return 0;
    }
    

    引用的本质

    本质:引用的本质在c++内部实现是一个常量指针
    int&a=b==>int* contst a=&b;
    指针指向不可以修改,但是其值可以修改
    PS:引用一旦初始化就不可以发生变化

    #include<iostream>
    using namespace std;
    void test(int& a)
    {
    	a = 
    
    下一篇:没有了