C++说爱你不容易-4
C++软件与嵌入式软件面经解析大全(蒋豆芽的秋招打怪之旅)
本章讲解点
- 1.1 C++与C的区别——看看你的理解是否深刻
- 1.2 从代码到可执行文件的过程
- 1.3 extern "C"
- 1.4 宏——到底是什么
- 1.5 内联函数
- 1.6 条件编译
- 1.7 字节对齐详解
- 1.8 Const——今天必须把它搞懂
- 1.9 Static作用
- 1.10 volatile和mutable
- 1.11 volatile在嵌入式里的应用
- 1.12 原子操作
- 1.13 指针与引用的区别
- 1.14 右值引用
- 1.15 面向对象的编程思想
- 1.16 类
- 1.17 类的成员
- 1.18 友元函数
- 1.19 初始化列表
- 1.20 this指针
- 1.21 继承
- 1.22 多态
- 1.23 虚函数与重写
- 1.24 虚构造函数与虚析构函数
- 1.25 函数重载
- 1.26 操作符重载
- 1.27 迭代器与指针
- 1.28 模板
- 1.29 C++智能指针
- 1.30 四种cast转换
- 1.31 Lambda
- 1.32 function和bind
受众:本教程适合于**C/C++**已经入门的学生或人士,有一定的编程基础。
本教程适合于互联网、嵌入式软件求职的学生或人士。
故事背景
**蒋 豆 芽:**小名豆芽,芳龄十八,蜀中人氏。卑微小硕一枚,科研领域苟延残喘,研究的是如何炒好一盘豆芽。与大多数人一样,学习道路永无止境,间歇性踌躇满志,持续性混吃等死。会点编程,对了,是面对对象的那种。不知不觉研二到找工作的时候了,同时还在忙论文,豆芽都秃了,不过豆芽也没头发啊。
**隔壁老李:**大名老李,蒋豆芽的好朋友,技术高手,代码女神。给了蒋豆芽不少的人生指导意见。
**导 师:**蒋豆芽的老板,研究的课题是每天对豆芽嘘寒问暖。
故事引入
导 师:我们基金即将结题,来写一下结题报告。
蒋 豆 芽:好的!(豆芽脸上笑嘻嘻)
蒋 豆 芽:(嘻嘻)哟,老李,今天有什么要教我的吗?
隔壁老李:(叹气)豆芽,最近我很忙啊,我在准备考教师资格证。
蒋 豆 芽:(疑惑)嗯?老李,你这编程这么厉害了,还考那干啥?做一个安静美美的程序员不好吗?
隔壁老李:(笑容邪魅)豆芽,你没听说过程序员中年危机吗?奋斗者协议听过没?
蒋 豆 芽:略有所闻,我这编程之路还没开始就要结束?
隔壁老李:哈哈,其实也没那么夸张啦,我逗你的,只有平庸的程序员才有中年危机,所以豆芽,学技术就要把它学好,技术学好了,人生的路口才会有更多的选择。也许成功的金字塔仅仅少数人才能登顶,但其他人可以横向发展,拓宽生命的宽度。。。。。。
蒋 豆 芽:(疑惑)嗯?老李,你打住,你怎么又开始哲理了。
隔壁老李:哈哈,我最近正在研究哲学与编程的辩证关系。
蒋 豆 芽:难怪疯疯癫癫了。
隔壁老李:(敲脑袋)懂个屁!好,今天我们继续来讲讲C++,今天内容就不一样了,是区别于C语言的知识,那就是类!
隔壁老李:豆芽,之前我们讲过C语言和C++的区别,你还记得吗?你可以打开你的小笔记本。
1.15 面向对象的编程思想
蒋 豆 芽:这个简单!C++最重要的特性就是在C语言基础上引入了面向对象的机制,所以两者最大的区别就是C++是面向对象的编程语言,C语言是面向过程的编程语言。
而为了实现面向对象的编程机制,C++引入了新的数据类型——类,由此引申出了三大特性(1)封装。(2)继承。(3)多态。
隔壁老李:我们要先从编程面向过程说起。
C语言是面向过程的编程语言。因为C语言是由函数实现结构化编程的,程序按顺序依次执行,非常符合我们人类解决问题的逻辑——按步骤一步一步来执行,最后解决问题。但是这会存在两个问题:
(1)机器就是按顺序执行,然后得到我们想要的结果。还记得我们刚入门编程的时候吗?我们就是在学习这种结构化编程,我们是在强迫自己按照计算机的思维写出代码,当整个软件规模庞大时,逻辑将复杂到人看着就头大的地步,无法进行维护和扩展。
(2)结构化设计是以功能为目标来构造应用系统,这样程序员不得不将客体所构成的现实世界映射到由功能模块组成的解空间中,这种转换过程,背离了人们观察和解决问题的基本思路。
蒋 豆 芽:这个我也有感受。在结构化设计构造系统时,当软件规模庞大,很难解决重用、维护、扩展的问题,逻辑很复杂,看着就头疼。
隔壁老李:所以前辈们就思考过,能不能让计算机直接模拟现实的环境,用人类解决问题的思路、习惯、步骤来设计相关的程序。我们人类的世界就是各个对象交互的世界,程序如果按照这样的逻辑来设计,我们人就会很容易理解,也不需要在现实世界与程序世界直接来回转换。这就是面向对象的编程思想。
所以豆芽你看,C++就隐含着前辈们对物理世界的思考与探索,是不是有点哲学内味儿了?
蒋 豆 芽:啧啧啧,别贫了,老李,继续。
隔壁老李:(蔑视)两者的区别就在于:面向过程的编程思想,就是关注问题解决的过程,按顺序一步一步执行解决问题。而面向对象的编程思想,是把构成问题的各个事务分解成各个对象,即问题建模。建立对象的目的不是为了完成一个步骤,而是为了描述一个事务在解决问题中经过的步骤和行为。
所以学习C++的同时也要学会面向对象的编程思想与方法,否则用着面向对象的编程语言,写出来的却是面向过程的代码,那可就让人啼笑皆非了。
蒋 豆 芽:哈哈,是的,这个必须的!豆芽记得以前去一家小公司实习,里面的代码,乖乖,全是用C++写的面向过程的代码。
隔壁老李:比如一个面向过程的程序员编程时,首先他会考虑遵循的步骤,然后考虑如何表示所要用到的数据;而如果是一个面向对象的程序员编程时,他会首先从用户的角度考虑对象——描述对象所需的数据以及描述用户与数据交互所需的操作。然后才完成接口的描述,最后创建程序。
蒋 豆 芽:那如何考虑对象呢?有什么思想来源吗?
隔壁老李:当然有,生活中的问题很复杂,而解决问题之前,我们一般的方法就是简化和抽象。
比如如何描述“刘亦菲”呢?那首先我们就要抽象这个概念,“刘亦菲”是”人”这个抽象的实体化,因此“刘亦菲”有着”人”该有的属性,“刘亦菲”有头、有脚等,“刘亦菲”也有着”人”该有的行为,如吃饭、睡觉。不仅“刘亦菲”是这样,“杨幂”也是这样,所以她们有着相同点,“人”这个抽象能很好地概括了她们,那么我们就可以定义一个“人”的数据结构来描述人。
这样我们就成功抽象了我们要解决的问题,我们没有单独研究“刘亦菲”的属性和行为,而是高屋建瓴,抽象出“人”的概念,研究“人”的属性和行为。这就是简化和抽象。
怎么样,豆芽,看见美女应该不困了吧?哈哈哈
蒋 豆 芽:(激动)没错!抽象是解决问题的思想,那方法是载体,抽象后如何变为代码呢?
1.16 类
隔壁老李:因此,我们就引入类了。C++为了更好的实现面向对象的编程思想,于是引入了新的数据类型——类。今天我们就来揭开类的神秘面纱。
蒋 豆 芽:(捂嘴)然后看看它长得漂不漂亮?
隔壁老李:(敲脑袋)能不能认真听讲?
隔壁老李:下面就是类类型的声明形式:
class 类名{//class,声明类的关键字
private:
私有的数据和成员函数;
public:
公有的数据和成员函数;
protected:
受保护的数据和成员函数;
};//分号结束
蒋 豆 芽:有什么区别?
隔壁老李:类中成员访问属性有三种:
(1)私有成员(变量和函数)只限于类成员访问,由private
限定;
(2)公有成员(变量和函数)允许类成员和类外的任何访问,由public
限定;
(3)受保护成员(变量和函数)允许类成员和派生类成员访问,不允许类外的任何访问。所以protected
对外封闭,对派生类开放。
豆芽你看,C++这样做都是有道理的,实现了很好的封装,这就是C++的第一个重要特性:封装性。所以我们写代码的时候经常要注意哪些成员对外开放?哪些成员对外关闭?
蒋 豆 芽:当存在派生类时,访问属性又是如何呢?
隔壁老李:豆芽问得好,笔试面试经常考这个问题。
类可以继承(继承允许我们依据另一个类来定义一个类,后面章节会详细讲解),那么此时成员访问属性会发生变化:
(1)public: 公有继承时,对基类的公有成员和保护成员的访问属性不变,派生类的新增成员可以访问基类的公有成员和保护成员,但是访问不了基类的私有成员。派生类的对象只能访问基类的公有成员(包括继承的公有成员),访问不了保护成员和私有成员。
(2)protected: 保护继承中,基类的公有成员和保护成员被派生类继承后变成保护成员,派生类的新增成员可以访问基类的公有成员和保护成员,但是访问不了基类的私有成员。派生类的对象不能访问基类的公有成员,保护成员和私有成员。
(3)private: 私有继承时,基类的公有成员和保护成员都被派生类继承下来之后变成私有成员,派生类的新增成员可以访问基类的公有成员和保护成员,但是访问不了基类的私有成员。派生类的对象不能访问基类的公有成员,保护成员和私有成员。
总结: 不管是哪种继承方式,派生类中新增成员可以访问基类的公有成员和保护成员,无法访问私有成员。但是只有公有继承中,派生类的对象能访问基类的公有成员。使用友元(friend)可以访问保护成员和私有成员。
以表格直观说明:
隔壁老李:为了更好地说明这个问题,我们来举个例子,这个例子笔试面试常考:
比如下面这个例题,Student1有几个受保护的成员?
class Student{
public:
void display();
protected:
int num;
string name;
char sex;
};
class Student1:protected Student{
public:
void display1();
private:
int age;
string addr;
};
蒋 豆 芽:简单!**保护继承中,基类的公有成员和保护成员被派生类继承后变成保护成员。**所以Student1有4个受保护的成员.
隔壁老李:没错!
蒋 豆 芽:太棒了!
1.17 类的成员
隔壁老李:类的成员有不少,我们说说几个重要的东西。先说说构造函数和析构函数。
-
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
给出实例:
#include <iostream> using namespace std; class Sprout{ public: void setLength( double len ); double getLength( void ); Sprout(void); // 这是无参数构造函数 Sprout(double len); // 这是带参数构造函数 private: double length; }; // 成员函数定义,包括构造函数 Sprout::Sprout(void){ cout << "Object is being created" << endl; } Sprout::Sprout( double len){ cout << "Object is being created, length = " << len << endl; length = len; } void Sprout::setLength( double len ){ length = len; } double Sprout::getLength( void ){ return length; } // 程序的主函数 int main(){ Sprout douya1; //调用无参数构造函数 Sprout douya2(10.0); //调用带参数构造函数 // 获取默认设置的长度 cout << "Length of line : " << douya2.getLength() <<endl; // 再次设置长度 douya2.setLength(6.0); cout <
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
<p> - 本专刊适合于C/C++已经入门的学生或人士,有一定的编程基础。 - 本专刊适合于互联网C++软件开发、嵌入式软件求职的学生或人士。 - 本专刊囊括了C语言、C++、操作系统、计算机网络、嵌入式、算法与数据结构等一系列知识点的讲解,并且最后总结出了高频面试考点(附有答案)共近400道,知识点讲解全面。不仅如此,教程还讲解了简历制作、笔试面试准备、面试技巧等内容。 </p> <p> <br /> </p>