c++领域睁开第一幕——入门根本(命名空间、iostream、缺省参数、函数重载 ...

打印 上一主题 下一主题

主题 986|帖子 986|积分 2960



  
前言

   本日小编带着大家进入c++的大门,虽然c++难,但功德多磨,一起来逐步啃下这个硬骨头吧
本日大致会了解c++的入门根本部分,fellow me
  一、c++的第一个步伐

   C++兼容C语言绝大多数的语法,以是C语言实现的hello world仍旧可以运行,C++中需要把定义文件代码后缀改为.cpp,vs编译器看到是.cpp就会调用C++编译器编译,linux下要用g++编译,不再是gcc
  1. // test.cpp
  2. #include<stdio.h>
  3. int main()
  4. {
  5.         printf("hello world\n");
  6.         return 0;
  7. }
复制代码
  固然C++有一套自己的输入输出,严格说C++版本的hello world应该是这样写的。
  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.         cout << "hello world\n" << endl;
  6.         return 0;
  7. }
复制代码
二、命名空间

2.1 namespace 的价值

   在C/C++中,变量、函数和反面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,大概会导致许多冲突利用命名空间的目的是对标识符的名称进行当地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种题目的。\
  c语言项目类似下面步伐这样的命名冲突是普遍存在的题目C++引入namespace就是为了更好的解决这样的题目
  1. #include <stdlib.h>
  2. int rand = 10;
  3. int main()
  4. {
  5.         // 编译报错: “rand”: 重定义;以前的定义是“函数”
  6.         printf("%d\n", rand);
  7. return 0;
  8. }
复制代码
2.2 namespace 的定义

   定义命名空间,需要利用到namespace关键字,反面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/范例等。
namespace本质是定义出一个域这个域跟全局域各自独立,差别的域可以定义同名变量,以是下面的rand不在冲突了。
  1. namespace xxx
  2. {
  3.         namespace yyy   //   嵌套定义  
  4.         {
  5.                 int rand = 1;
  6.                 int Add(int left, int right)
  7.                 {
  8.                         return left + right;
  9.                 }
  10.         }
  11.         namespace zzz
  12.         {
  13.                 int rand = 2;
  14.                 int Add(int left, int right)
  15.                 {
  16.                         return (left + right) * 10;
  17.                 }
  18.         }
  19. }
  20. int main()
  21. {
  22.         printf("%d\n", xxx::yyy::rand);
  23.         printf("%d\n", xxx::zzz::rand);
  24.         printf("%d\n", xxx::yyy::Add(1, 2));
  25.         printf("%d\n", xxx::zzz::Add(1, 2));
  26.         return 0;
  27. }
复制代码

有代码和运行截图,才华更好的明确
   C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找一个变量/函数/范例出处(声明或定义)的逻辑,以是有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。
    namespace只能定义在全局,固然他还可以嵌套定义
项目工程中多文件中定义的同名namespace会认为是一个namespace,不会冲突。
C++尺度库都放在一个叫std(standard)的命名空间中。
  2.3 命名空间的利用

   编译查找一个变量的声明/定义时,默认只会在局部大概全局查找,不会到命名空间内里去查找。以是下面步伐会编译报错。以是我们要利用命名空间中定义的变量/函数,有三种方式:
指定命名空间访问,项目中推荐这种方式。
using将命名空间中某个成员睁开,项目中经常访问的不存在冲突的成员推荐这种方式
睁开命名空间中全部成员,项目不推荐,冲突风险很大,一样平常小训练步伐为了方便推荐利用。
  1. #include<stdio.h>
  2. namespace N
  3. {
  4.         int a = 0;
  5.         int b = 1;
  6. }
  7. int main()
  8. {
  9.         // 编译报错: “a”: 未声明的标识符
  10.         printf("%d\n", a);
  11.         return 0;
  12. }
  13.         // 指定命名空间访问
  14. int main()
  15. {
  16.         printf("%d\n", N::a);
  17.         return 0;
  18. }
  19. // using将命名空间中某个成员展开
  20. using N::b;
  21. int main()
  22. {
  23.         printf("%d\n", N::a);
  24.         printf("%d\n", b);
  25.         return 0;
  26. }
  27. // 展开命名空间中全部成员
  28. using namespace N;
  29. int main()
  30. {
  31.         printf("%d\n", a);
  32.         printf("%d\n", b);
  33.         return 0;
  34. }
复制代码
三、c++的输入和输出

   • 是 Input Output Stream 的缩写,是尺度的输入、输出流库,定义了尺度的输入、输出对象。
std::cin 是 istream 类的对象,它主要面向窄字符的尺度输入流。
• std::cout 是 ostream 类的对象,它主要面向窄字符的尺度输出流。

• std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。
• <<是流插入运算符,>>是流提取运算符。(C语言还用这两个运算符做位运算左移/右移
• 利用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动指定格式,C++的输入输出可以自动识别变量范例,其实最重要的是
C++的流能更好的支持自定义范例对象的输入输出
• IO流涉及类和对象,运算符重载、继续等许多面向对象的知识,我们后续会逐步学习的,以是这里我们只能简单认识一下C++ IO流的用法。
• cout/cin/endl等都属于C++尺度库,C++尺度库都放在一个叫std(standard)的命名空间中,以是要通过命名空间的利用方式去用他们
一样平常一样平常训练中我们可以using namespace std,实际项目开发中不建议using namespace std。
• 这里我们没有包含<stdio.h>,也可以利用printf和scanf,在包含间接包含了。vs系列编译器是这样的,其他编译器大概会报错。
  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.         int a = 0;
  6.         double b = 0.1;
  7.         char c = 'x';
  8.         cout << a << " " << b << " " << c << endl;
  9.         std::cout << a << " " << b << " " << c << std::endl;
  10.         scanf("%d%lf", &a, &b);
  11.         printf("%d %lf\n", a, b);
  12.         // 可以自动识别变量的类型
  13.         cin >> a;
  14.         cin >> b >> c;
  15.         cout << a << endl;
  16.         cout << b << " " << c << endl;
  17.         return 0;
  18. }
复制代码
cin和cout用起来还是很爽的
四、缺省参数

   缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则利用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
全缺省就是全部形参给缺省值半缺省就是部分形参给缺省值半缺省参数必须从右往左依次连续缺省,不能隔断跳跃给缺省值。
带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参
函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。
  1. #include <iostream>
  2. using namespace std;
  3. void Func(int a = 0)
  4. {
  5.         cout << a << endl;
  6. }
  7. int main()
  8. {
  9.         Func(); // 没有传参时,使用参数的默认值
  10.         Func(10); // 传参时,使用指定的实参
  11.         return 0;
  12. }
复制代码
  1. #include <iostream>
  2. using namespace std;
  3. // 全缺省
  4. void Func1(int a = 10, int b = 20, int c = 30)
  5. {
  6.         cout << "a = " << a << endl;
  7.         cout << "b = " << b << endl;
  8.         cout << "c = " << c << endl << endl;
  9. }
  10. // 半缺省
  11. void Func2(int a, int b = 10, int c = 20)
  12. {
  13.         cout << "a = " << a << endl;
  14.         cout << "b = " << b << endl;
  15.         cout << "c = " << c << endl << endl;
  16. }
  17. int main()
  18. {
  19.         Func1();
  20.         Func1(1);
  21.         Func1(1,2);
  22.         Func1(1,2,3);
  23.         Func2(100);
  24.         Func2(100, 200);
  25.         Func2(100, 200, 300);
  26.         return 0;
  27. }
复制代码

可以细致看看代码体会一下
   还有一点要注意的是,缺省参数只能在函数的声明部分给,不能在定义部分给
  1. // Stack.h   .h文件  函数的声明  这里用以前实现过的栈举例子
  2. #include <iostream>
  3. #include <assert.h>
  4. using namespace std;
  5. typedef int STDataType;
  6. typedef struct Stack
  7. {
  8.         STDataType* a;
  9.         int top;
  10.         int capacity;
  11. }ST;
  12.         void STInit(ST* ps, int n = 4);   //  这里的n = 4  就是缺省参数
复制代码
  1. // Stack.cpp   函数的定义文件  
  2. #include"Stack.h"
  3. // 缺省参数不能声明和定义同时给
  4. void STInit(ST* ps, int n)  //  函数的定义  这部分不能给缺省值
  5. {
  6.         assert(ps && n > 0);
  7.         ps->a = (STDataType*)malloc(n * sizeof(STDataType));
  8.         ps->top = 0;
  9.         ps->capacity = n;
  10. }
复制代码
  1. // test.cpp   测试文件
  2. #include"Stack.h"
  3. int main()
  4. {
  5.         ST s1;
  6.         //  不确定数据的多少,这里不传参数,函数会用默认参数  
  7.         STInit(&s1);
  8.         ST s2;
  9.         // 确定知道要插入1000个数据,初始化时一把开好,避免扩容
  10.         STInit(&s2, 1000);
  11.         return 0;
  12. }
复制代码
五、函数重载

   C++支持在同一作用域中出现同名函数,但是要求这些同名函数的形参差别,可以是参数个数差别大概范例差别。这样C++函数调用就体现出了多态行为,利用更灵活。C语言是不支持同一作用域中出现同名函数的。
    参数范例差别
  1. #include<iostream>
  2. using namespace std;
  3. int Add(int left, int right)
  4. {
  5.         cout << "int Add(int left, int right)" << endl;
  6.         return left + right;
  7. }
  8. double Add(double left, double right)
  9. {
  10.         cout << "double Add(double left, double right)" << endl;
  11.         return left + right;
  12. }
复制代码
  参数个数差别
  1. void f()
  2. {
  3.         cout << "f()" << endl;
  4. }
  5. void f(int a)
  6. {
  7.         cout << "f(int a)" << endl;
  8. }
复制代码
  参数顺序范例差别
  1. // 3、参数类型顺序不同
  2. void f(int a, char b)
  3. {
  4.         cout << "f(int a,char b)" << endl;
  5. }
  6. void f(char b, int a)
  7. {
  8.         cout << "f(char b, int a)" << endl;
  9. }
复制代码
  需要注意一些环境
  1. // 返回值不同不能作为重载条件,因为调用时也无法区分
  2. void fxx()
  3. {}
  4. int fxx()
  5. {
  6.         return 0;
  7. }
复制代码
  1. // 下面两个函数构成重载
  2. // f()但是调用时,会报错,存在歧义,编译器不知道调用谁  这里就是参数缺省背锅了
  3. void f1()
  4. {
  5.         cout << "f()" << endl;
  6. }
  7. void f1(int a = 10)
  8. {
  9.         cout << "f(int a)" << endl;
  10. }
复制代码
六、nullptr

   NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
  1. #ifndef NULL
  2.         #ifdef __cplusplus
  3.                 #define NULL 0
  4.         #else
  5.                 #define NULL ((void *)0)
  6.         #endif
  7. #endif
复制代码
  C++中NULL大概被定义为字面常量0,大概C中被定义为无范例指针(void)的常量*。不论采取何种定义,在利用空值的指针时,都不可避免的会遇到一些麻烦,本想通过f(NULL)调用指针版本的f(int)函数,但是由于NULL被定义成0,调用了f(int x),因此与步伐的初志相悖。f((void)NULL);调用会报错。**
• C++11中引入nullptr,nullptr是一个特别的关键字nullptr是一种特别范例的字面量,它可以转换成恣意其他范例的指针范例。利用nullptr定义空指针可以避免范例转换的题目,由于nullptr只能被隐式地转换为指针范例,而不能被转换为整数范例。
  1. #include<iostream>
  2. using namespace std;
  3. void f(int x)
  4. {
  5.         cout << "f(int x)" << endl;
  6. }
  7. void f(int* ptr)
  8. {
  9.         cout << "f(int* ptr)" << endl;
  10. }
  11. int main()
  12. {
  13.         f(0);
  14.         // 本想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,调用了f(intx),因此与程序的初衷相悖。
  15.         f(NULL);
  16.         f((int*)NULL);
  17.         // 编译报错: “f”: 2 个重载中没有一个可以转换所有参数类型
  18.         // f((void*)NULL);
  19.         f(nullptr);
  20.         return 0;
  21. }
复制代码
  以是c++部分尽量就用nullptr就好啦
  七、inline

   • 用inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方睁开内联函数这样调用内联函数就不需要创建栈帧了,就可以提高服从。
• inline对于编译器而言只是一个建议,也就是说,你加了inline编译器也可以选择在调用的地方不睁开,差别编译器关于inline什么环境睁开各不相同,由于C++尺度没有规定这个inline实用于频繁调用的短小函数,对于递归函数,代码相对多一些的函数,加上inline也会被编译器忽略
也就是说,在inline这个方面,编译器占主导地位
    • C语言实现宏函数也会在预处理时更换睁开,但是宏函数实现很复杂很轻易出错的,且不方便调试,C++计划了inline目的就是替代C的宏函数。
• vs编译器 debug版本下面默认是不睁开inline的,这样方便调试
inline不建议声明和定义分离到两个文件,分离会导致链接错误。由于inline被睁开,就没有函数地点,链接时会出现报错。
    这里内联函数就是睁开的,没有特别多的斲丧,如果一个简短的函数调用次数许多许多,这个时间就可以用内联睁开,淘汰函数栈帧的创建,提高服从
  1. #include<iostream>
  2. using namespace std;
  3. inline int Add(int x, int y)
  4. {
  5.         int ret = x + y;
  6.         ret += 1;
  7.         ret += 1;
  8.         ret += 1;
  9.         return ret;
  10. }
  11. int main()
  12. {
  13.         int ret = Add(1, 2);
  14.         cout << Add(1, 2) * 5 << endl;
  15.         return 0;
  16. }
复制代码
  1. #include<iostream>
  2. using namespace std;
  3. // 实现一个ADD宏函数的常见问题
  4. //#define ADD(int a, int b) return a + b;  这三个是一些错误的宏的实现
  5. //#define ADD(a, b) a + b;
  6. //#define ADD(a, b) (a + b)
  7. // 正确的宏实现
  8. #define ADD(a, b) ((a) + (b))   //  每个参数都加括号是  因为 a 也可能是一个表达式或者是其他的情况
  9. int main()
  10. {
  11.         int ret = ADD(1, 2);
  12.         cout << ADD(1, 2) << endl;
  13.         cout << ADD(1, 2)*5 << endl;
  14.         int x = 1, y = 2;
  15.         ADD(x & y, x | y); // -> (x&y+x|y)
  16.         return 0;
  17. }
复制代码

总结

   本日入门了c++的基本语法,从第一个c++步伐到命名空间对c语言命名冲突的优化,再来到缺省参数的魅力,然后是函数重载,接着是nullptr和NULL的区别以及长处,末了是类似于宏函数但优于宏函数的内联函数
c++在各个方面都在优化c语言,把以前不能实现大概有缺点的都进行了优化,不愧是c puls puls
本日的学习就到这里啦,下一篇博客小编将带着大家学习一个比指针好用的东西,不要走开,小编连续更新中~~~
  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81428

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表