【C++01】吾与C加初相识

泽西:「这艘飞船的所有核心功能基本上都是利用C++语言实现的。这是深思熟虑的结果,毕竟这样做的优点有很多。」世昌:「C语言还知道点,C++还真不熟,这很重要吗?我的意思是,如果不掌握会限制我的行动?」泽西:「没关系,等你吃到不会C++的苦头你就主动去学了。我一点都不担心。」世昌:「我信你,我还是主动一点吧,以免你们觉得我没价值,一脚给我踢出飞船。」
次日上午世昌早早来到图书馆借了很多有关C++的书,只是简单的翻了几页就已经不心烦意乱。这种看书学习的方法不太行。还是得想其他的办法,眼下还是去找泽西指导一下吧,但是他每天都忙的不行,我有点事儿就去找他是不是太恶心人了。先去找一趟小薇吧,毕竟小薇看起来比较亲切,在我的平行世界也算是老情人吧。
世昌:「薇在吗?薇在吗?」小薇:「干嘛呢,干嘛呢?哟,刘大官人,空着手来呀。」世昌:「这不是来的着急忘了嘛,你教我C++,你可别急着拒绝,我知道你肯定会。」小薇:「我可以教你,但是你得答应我一个条件。」世昌:「什么条件??」小薇:「等我想好了告诉你,你不许反悔我就教你,我保证可以教会你C++。就看你想不想学了」世昌虽然很想知道小薇脑袋里酝酿着什么鬼点子,但是一想到泽西之前的话这会儿也关不了太多了。直接就答应了小薇的要求。小薇:「我给你一个学习秘籍,但是你得自己闭关修炼一个月。每天早上8点找我领取当天秘籍。如果你不按照我秘籍修炼,大概率你得吃苦头了。」世昌:「太棒了薇薇宝贝,这样你也可以每天了解我的进度,不懂的还以问你。赶快告诉我第一天的秘籍吧,我准备好了。」小薇:「大哥麻烦你看看表,已经下午了大哥,我知道你很急,但你先别急。明天早上八点准时来找我吧。别烦我了,我还有别的事情,谁像你一样,天天那么闲。」世昌:「诺,臣先告退!」。小薇:「滚滚滚~又不正经。」。
修炼第一天:C++介绍
「早上好,你好!在吗?」世昌准时来到小薇家门口,敲响小薇家的门。「别敲了,来了,来了。拆门吗大哥?」小薇穿着淡粉色的睡裙,头发也是乱乱的,揉着眼睛给世昌开门。小薇曼妙的身材在门外微风的亲抚下,在裙子上形成一层又一层的涟漪。涟漪像是巨浪一样打在世昌的心坎里面。现在世昌满脑子想的是,这谁顶得住啊,小薇身材配和颜值也太顶了吧。不争气的嘴也不自觉的结巴「薇~薇你~你,你这睡睡醒了啊。」小薇「你怎么了?路上着凉了?说话咋吞吞吐吐的。进来吧,等我洗漱洗漱整理整理。」世昌「好~好~这样不好吧。」小薇「你好好说话,坐到沙发上等我,警告你别瞎逛,别偷看。」
不久后,小薇很正式的穿上了一条白色长裙。很正式的走到世昌面前。拿出一个盒子,盒子里面精心装着一个本子和一枚戒指,戒指是黄金圆环上镶嵌了一颗海蓝宝宝石。世昌调侃的问到「你是不是结婚了,你给盒子里藏着一枚戒指干啥,怕自己嫁不出去吗?」小薇并没有生气,也没有迎合世昌的调侃只是默默的把本子拿了出来说「这个本子其实我早就写好了,我也只要有一天会给你。至于秘籍其实就是一个学习C++的路径,经过长时间的总结发现这样的学习路线是最科学,最能扎实掌握的方法。但是因人而异吧。毕竟没有什么是最终的答案。我把今天你要学的东西给你。」随后小薇把本子上第一页纸撕下递给世昌,世昌接过纸后与小薇简单的告别,就离开小薇家,一人来到了图书馆。有了这份学习路径,就可以清楚的明白自己要寻找那些知识去学。世昌依然在图书馆找了几本资料书,这些资料书都特别的陈旧,上面已经布满了灰尘。也是打了好几个喷嚏才习惯了书籍上残留的🤮尘土味儿。世昌掏出秘籍,从第一部分看。
更好的C
C++和C一样,都属于编译型语言
C++和C一样,都属于强类型语言
C++对C完全兼容,对其中做了优化并提出更多的特性
—语言风格更加简洁
—类型检查更加严格
—支持面向对象编程
—支持操作符重载
—支持异常处理
—支持泛型编程
这个秘籍怎么这么简陋了,我只能自己查阅资料了。看看能不能回答这些问题。世昌开始在电脑查阅资料阅读各种文献。最后也是得出来一些心得。
C语言崇尚自由。
C++崇尚安全。
 C语言设计之后是给大神用,大神自己可以把控安全问题。如果C语言限制太多,是对大神的侮辱,我都是大神了,你C语言还给我那么多的限制。多冒昧啊。
 C++设计出来后主要服务的对象是开发人员水平不太行的,你C++语言提供自由度太大就不太行。
第一个C++程序:01_hello.cpp
目的:体验C++程序和C程序的差别。

1.编译器换成了g++  01_hello.cpp  -o
如果还想用gcc编译器就需要gcc  01_hello.cpp  -lstdc++ 后面要加这个选项。
2.#include <iostream>不是所有的头文件都必须有.h后缀。这个目录在/usr/include/c++目录中。
3.std::cout << "hello world" << std::endl;
:: 就读“中的”
cout就是一个对象,C++中万物皆对象。
<<不是C中的左移。今天就理解成箭头吧。把hello world插入到std::cout

名字空间
为什么需要名字空间——why?
—划分逻辑单元,避免名字冲突 nameconf.cpp
什么是名字空间——what?
—名字空间定义 namespace 名字空间名字 {...}
—名字空间合并 nameconf.cpp
—声明定义分开 nameconf.cpp
怎样用名字空间——how?
—作用域限定符 : :
—名字空间指令 diruse.cpp
—名字空间声明 impname.cpp
在C语言中划分空间简单粗暴,甚至有点简陋。只是全局域 / 部分域
C++可以划分更多的作用域,可以有效避免名字冲突。就比如说起名字,家里苦思冥想给起了一个“刘世昌”的名字,发现被占用了。你总不想改名“刘世昌1”...“刘世昌666”。这里解决的其实就是这个问题。

namespace ICBC{

namespace CCB{
}
namespace ICBC{

一个程序中有两个相同的名字并不会报错。
合并==>编译器去合并==>把程序散落在不同位置的同名空间会合并为一个名字空间
为什要把名字空间拆分去写然后又叫编译器去合并?
缺点:增加了代码量。
优点:C语言适合小而精的程序,C++适合大型程序代码,一般几万行的代码,一般是多个人一起开发的程序。这时候就显现出来C++的优势。


例如:我是老板,我只是给两个项目组一组一个名字空间就行了。
把大家分成两个组,A组和B组
A组:主要负责ICBC银行业务。
B组:主要负责CCB银行业务。
这样的话两个组名字写一样也没问题。好处就是大大降低了沟通成本。
A小组中不论是小刘,小李或者是小周写的代码。我都用同一个名字空间。之后编译时,编译器就把小刘,小李……的名字空间合在一起。
《团队开发》

声明定义也可以分开写
namespace CCB{
Void pay (int money);//声明
}
Void CCB::pay(int money){ //定义
}
为什么定义和声明不写在一起?
声明写在头文件中去给用户看,定义是我自己的知识产权,是我要赚钱吃饭的家伙,当然不希望别人看到。
怎样使用名字空间
一、作用域限定符: :(高可靠)
这个::就相当于江湖里的黑话,在IT行业如果可以说一口流利的黑话显得很专业。
用::使用名字空间里的内容,是高可靠的。
CCB::save(100);
这样就使用了CCB中的save函数,好处就是高可靠,但是也有缺点,这样写的话太麻烦了。得累死程序员。随后就引出了其他两种使用方法。
二、名字空间指令(低可靠)diruse.cpp
using namespace ns;
这句话就是名字空间指令。
含义:从这行代码开始,ns中内在当前作用域可见。
缺点:在main中定义的同名变量会有问题。
补充知识:编译器在弄每个函数时,都会弄两张表。就类似于是编译器的演草纸。


定义表

可见表
1这两个表没有存在你的最终文件里保存。他不会进入你的进程映像。
2提供给编译器,编译器把函数给编完后这两张表就会销毁。
3  main函数中定义的标识符都在“定义表”中。
标识符:程序中所有的名字(例如变量名字,函数名……)
优先到定义表找标识符,定义表没有再去找可见表。

三、名字空间声明(低可靠)
main( ){
using ns::g_value; //从这行代码开始,ns中的g_value引入当前作用域,(相当于定义)
}

名字空间指令和名字空间声明dclhide.cpp体验两者的差别。
个人感悟:🫴把握好标识符在“定义表”和“可见表”什么位置就不会弄迷了。

名字空间嵌套
namespace ns1{
namespace ns2{
namespace ns3{
namespace ns4{
......
}

}
}
cout << ns1::ns2::ns3::ns4::g_value <<endl;
这样也太麻烦了,之后嵌套的名字空间需要逐层分解。

名字空间别名可以简化书写
namespace ns_four = ns1::ns2::ns3::ns4;

第一天的学习,世昌已经对C++语言有了初步的认识,走出图书馆天色已是黄昏,天边泛起了赤色的晚霞,但是心情确无比的喜悦。现在世昌只想赶快干饭,加鸡腿加鸡腿。


修炼第二天:C++介绍
C++复合类型
C++的结构         type.cpp
-定义结构型的变量时,可以省略struct关键字
-可以定义成员函数,在结构体中的成员函数内部可以直接访问本结构体的成员,无需通过“.”,“->”。

C++的联合         type.cpp
-定义联合型的变量时,可以省略union关键字
-支持匿名联合


C++的枚举     type.cpp
-定义枚举型的变量时,可以省略enum关键字
-独立的类型,和整型之间不能隐式转换。

布尔类型
表示布尔量的数据类型      type.cpp
-bool
布尔类型的字面值常量
-true表示真
-false表示假
布尔类型的本质
-单字节整数,用1和0表示真和假
任何基本类型都可以被隐式转换为布尔类型
-非0即真,0即假

函数关系——重载
重载关系 overload.cpp
-同一作用域内,函数名相同,参数表不同
-根据实参类型和形参的类型进行匹配,调用最匹配的函数
-只有同一作用域内的同名函数才涉及重载的关系,不同作用域的同名函数涉及的是隐藏关系。   overload2.cpp
重载解析   overload3.cpp
-完全匹配>常量转换>升级转换>标准转换>自定义转换>省略号匹配
函数指针的类型决定其调用的重载函数的版本


重载的本质
重载是通过C++换名机制来实现的
C++国际标准 规定 全天下的C++编译器都要对函数进行换名(换名机制),但是换名规则都不相同。
    int sum( int a, int b ) { }
    g++    :   _Z3sumii
    cl.exe  :   ?sumYAHHH@Z
    ...

通过extern “C”可以要求C++编译器按照C方式编译函数,即不做换名,当然也就无法重载。范例代码 : extern
   - nm工具   nm a.out查看符号表

哑元函数
只指定形参类型而不指定形参名称的函数,谓之哑元
-保证函数的向下兼容
-形成函数的重载版本
范例代码 : forover.cpp


缺省(默认)参数
可以为函数的形参指定缺省(默认)值,当调用该函数时若未指定实参,则使用形参的缺省(默认)值。
如果函数的某一个形参具有缺省(默认)值,那么该形参后面的所有形参必须都具有缺省(默认)值
尽量避免因为使用缺省参数而导致重载匹配歧义
函数形参的缺省(默认)值只能在函数声明中指定
     范例代码 : defparam.cpp

代码中从double b=3.14开始,后面的所有都需要给默认参数。因为如果形参给了,后面的参数都要给。
注意:不要发生重载冲突。只能声明和定义写在一起。

修炼第三天:C++的函数、动态内存管理
内联函数
调用普通函数的问题:
    每个普通函数调用语句都需要发生跳转操作,这种跳转操作会带来时间开销。     范例 : inline.cpp

内联就是用函数已被编译好的二进制代码,替换对该函数的调用指令
内联在保证函数特性的同时,避免了函数调用的时间开销
范例 : inline.cpp

内联函数总结
内联会使可执行文件的体积和进程代码的内存变大,因此只有频繁调用的简单函数才适合内联
inline关键字仅表示期望该函数被优化为内联,但是否适合内联则完全由编译器决定
稀少被调用的复杂函数和递归函数都不适合内联
个人总结:并不是所有函数都需要内敛,没有完美的技术,用一次就不用的函数没有必要内联。


动态内存分配
可以继续使用标准C库函数malloc/free
更建议使用new/delete操作符在堆中分配/释放内存
-int* pi = new int;
    -delete pi;
在分配内存的同时初始化
-int* pi = new int (100);
以数组方式new的也要以数组方式delete
-int* pi = new int [4] {10, 20, 30, 40};
    -delete[] pi;

不论几维数组,都应该当做一维数组看待。

通过new操作符分配N维数组,返回N-1维数组指针
-int (*prow) [4] = new int [3][4];
-int (*ppage) [4][5] = new int [3][4][5];

不能通过delete操作符释放已释放过的内存

delete野指针后果未定义,delete空指针安全

new操作符申请内存失败,将抛出异常


引用
引用就是C++的灵魂,指针是C的灵魂。
引用就是一块内存的别名。通过打印地址可以证明。
引用即内存的别名   alias.cpp
-int a = 10;
     int& b = a;

引用本身不占内存,并非实体, 对引用的所有操作都是在对目标内存进行操作

引用必须初始化,且不能更换目标
-int c = 20;
     b = c;//仅仅是在对引用的目标内存进行赋值


不存在引用的引用    alias.cpp
int a = 10;
    int& b = a;
    int& d = b;

引用的常属性须和目标的常属性“一致”
const int e = 10;
    int& f = e;//ERROR
    const int& g = e;//OK

可以限定更加严格
Int a = 10;
    const int& h = a;//OK


引用可以延长右值的生命周期
常引用  即  万能引用 
引用的生命周期不能长于目标

常引用 即 万能引用( 可以引用 非常左值、常左值、右值)
    常指针 即 万能指针( 可以指向 非常左值、常左值、右值)
       int a = 10;
       const int& cra = a; 
// 但如果常引用 引用的为 非常左值,那么通过常引用将丧失修改目标内存的权限
       const int* pra = &a; 
// 但如果常指针 指向的为 非常左值,那么通过常指针将丧失修改目标内存的权限

引用的应用
引用型参数,函数的形参是实参的别名,避免对象复制的开销
非常引用型参数
-在函数中修改实参值          vparam.cpp
常引用型参数
-防止对实参的意外修改        vparam.cpp
-接受常量型实参

引用型的返回值,从函数中返回引用,一定要保证在函数返回以后,该引用的目标依然有效
-可以返回全局、静态变量的引用
-可以返回成员变量的引用
-可以返回在堆中动态创建的对象的引用
-可以返回调用对象自身的引用
-可以返回引用型参数本身
-不能返回局部变量的引用
非常引用型返回值
-通过引用可以修改目标
常引用型返回值
-通过引用不能修改目标

在实现层面,引用就是指针,但在C++语言层面,引用不是实体类型,因此C++语言层面引用与指针存在明显的差别
-指针可以不初始化,而引用必须初始化。
-指针的目标可在初始化后随意变更(除非是指针常量),而引用一旦初始化就无法变更其目标
-存在空指针,不存在空引用
-存在指向指针的指针,不存在引用的引用
-存在指针的引用,不存在引用的指针
-存在指针数组,不存在引用数组,但存在数组引用

07_poi_ref


类型强转换
显式类型转换           convert.cpp
C风格的显式类型转换
-(目标类型)源类型变量
C++风格的显式类型转换
-目标类型(源类型变量)
静态类型转换
-static_cast<目标类型> (源类型变量)
-隐式类型转换的逆转换
-自定义类型转换

动态类型转换
-dynamic_cast<目标类型> (源类型变量)
-多态父子类指针或引用之间的转换
常类型转换
-const_cast<目标类型> (源类型变量)
-去除指针或引用上的const属性
重解释类型转换
-reinterpret_cast<目标类型> (源类型变量)
-任意类型的指针之间的转换或引用之间的转换
-任意类型的指针和整型之间的转换

面向对象
什么是面向对象——WHAT?
- 万物皆对象,这是人类面对世界最朴素,最自然的认知、感觉。
- 把大型软件看成是由多个对象组成的团队。
- 对象拥有足够的智能,能够理解来自其它对象的信息,并以适当的行为作出反应。
- 对象能够从高层对象继承属性和行为,并允许低层对象从自己继承属性和行为等
- 面向对象的三大要件:封装、继承和多态

为什么要面向对象——WHY?
- 相比于分而治之的结构化程序设计,强调大处着眼的面向对象程序设计思想,更适合于开发大型软件
- 得益于代码复用等面向对象的固有特征,软件开发的效率获得极大地提升,成本却大幅降低
- 面向对象技术的表现如此出众,以至于那些原本并不直接支持面向对象特性的语言(例如C),也在越来越多地通过各种方法模拟一些面向对象的软件结构

怎样面向对象——HOW?
-至少掌握一种面向对象的程序设计语言,如C++
-深入理解封装、继承和多态等面向对象的重要概念
-学习设计模式,源自多年成功经验的积累和总结

相关推荐

  1. C++01C相识

    2024-04-11 14:26:01       13 阅读

最近更新

  1. Matlab 使用

    2024-04-11 14:26:01       0 阅读
  2. AI学习指南机器学习篇-层次聚类原理

    2024-04-11 14:26:01       0 阅读
  3. k8s-第一节-minikube

    2024-04-11 14:26:01       1 阅读
  4. 基于gunicorn+flask+docker模型高并发部署

    2024-04-11 14:26:01       1 阅读
  5. 数据无忧:Ubuntu 系统迁移备份全指南

    2024-04-11 14:26:01       1 阅读
  6. 3.配置MkDocs

    2024-04-11 14:26:01       1 阅读
  7. AI学习指南机器学习篇-层次聚类距离度量方法

    2024-04-11 14:26:01       1 阅读
  8. 中介子方程五十

    2024-04-11 14:26:01       1 阅读

热门阅读

  1. 从零开始的LeetCode刷题日记:28. 实现 strStr()

    2024-04-11 14:26:01       15 阅读
  2. 医美行业专用服务器:为您的业务保驾护航

    2024-04-11 14:26:01       16 阅读
  3. 二进制转十进制快速方法

    2024-04-11 14:26:01       11 阅读
  4. 美国发布玩具安全标准ASTM F963-23

    2024-04-11 14:26:01       13 阅读
  5. Vue 的父组件和子组件生命周期钩子函数执行顺序

    2024-04-11 14:26:01       15 阅读
  6. 前端面试题大合集

    2024-04-11 14:26:01       13 阅读
  7. Vue项目Nginx配置自定义路径别名

    2024-04-11 14:26:01       17 阅读