【针对性复习】1大锅乱炖

静心、专注、思考....

目录

  • day 6

C/C++中涉及到的知识点:

  1. 数组

  2. 指针

  3. 结构体内存对齐

  4. 函数调用过程

  5. C语言中的动态内存管理

  6. 进行文件操作常用的API

  7. str系列和mem系列函数的模拟实现

  8. static和extern

  9. 不定参数的函数

一、内联函数?宏函数和内联函数的区别?C++中有哪些方式可以替代宏?

    宏函数的优缺点:

  • 优点:在预处理节点,预处理器会将宏函数展开,少了函数调用过程开销---提高程序的运行效率

  • 缺陷:不是真正的函数,在预处理阶段展开,因此不参加编译,不方便调试

  • 宏函数的副作用:代码膨胀

内联函数:被inline关键字修饰的函数,成员函数放在类中被定义

  1. 注意inline建议性关键 原则:不能太长,循环,递归

  2. 在编译阶段,编译器会将内联函数展开--少了函数调用开销

优点:

  • 真正的函数,参与编译,对参数进行类型检测--安全性比较高

  • debug模式下,编译器不会展开

缺陷:代码膨胀

宏常量:const类型的常量:在编译阶段,直接替换。

二、类和对象

什么是封装?

1、概念:将一个事物内部细节隐藏,必须暴露一些公有的接口让对象之间进行交互;

2、例子:

class Student{                     //类名称

private:                        //私有属性
    string name;                   //成员变量,名称              
public:
    Student(string& name){                 //构造函数
       this->name = name;
    }
    ~Student(){}                    //析构函数
    void Study(){                  //成员函数
        cout << "学习" << endl;
    }
};

函数是封装的一种形式:函数所执行的细节行为被封装在函数本身这个更大的实体中,被封装的元素隐藏了它们的实现细节–可以调用一个函数但是不能够访问函数所执行的语句。

因此,封装相当于就是class+访问限定符。

注意:访问限定符本质上是给编译器使用的,数据放在内存中没有任何限制的。

 

<1.函数名相同,参数表不同的才叫做函数重载。那两个函数一个是构造,一个是析构,不是函数重载。

<2.C++的封装就是说把一个对象封装成类,并设置成员的访问权限(public公有,protected保护,private私有)学生是一个对象,封装成类Student,类里面有属性和操作,属性就是name,每个学生都有名称吧,操作就是Study,学生就是要学习的,不是吗,而构造函数和析构函数是类必不可少的部分,用于创建对象和回收资源,如果你不写,系统也会给你默认的构造和析构,如果没有复杂的成员的话,系统默认的构造析构也就够用了。

3、C++中如何实现封装:

  • 类:将对象的属性和方法包装在一起;

  • 访问权限:通过访问权限选择性将方法提供给外部进行使用private/protected/public

4、C++中class和struct的区别?

  • class默认是private,struct默认是public。

  • struct更适合看成是一个数据结构的实体,class更适合看成是一个对象的实现体。

  • class和struct如果定义了构造函数的化,都不能用大括号进行初始化。

5、this指针?

关于this指针的一个经典回答:

当你进入一个房子后,   

你可以看见桌子、椅子、地板等,   

但是房子你是看不到全貌了。   

对于一个类的实例来说,   

你可以看到它的成员函数、成员变量,   

但是实例本身呢?   

this是一个指针,它时时刻刻指向你这个实例本身

  • this指针只能在成员函数内部使用;

  • this在成员函数的开始前构造,在成员函数的结束后清除;

几个常见问题?

1.this指针是什么时候创建的?

答:采用new的方式创建对象的话,在队里分配内存,new操作符通过eax返回分配的地址,然后设置给指针变量。

2.this指针内存放在何处?堆、栈、全局变量、还是?

答:this只会因编译器不同而有不同的位置。(栈、寄存器、全局变量....)

在成员函数中,你是可以知道this指针的位置的(可以通过&this获得),也可以直接使用它。

3.this之如何传递类中的函数?

答:大多数编译器通过ecx寄存器传递this指针。(泪在实例化时,只分配类中的变量空间,并没有为函数分配空间)

4.普通的类函数(不论是成员函数,还是静态函数)都不会创建一个函数表来保存函数指针。只有虚函数才会被放到函数表中。

 

6、空类的大小?为什么?【定义了一个空的类型,里面没有任何成员变量和成员函数。对该类型求sizeof,得到的结果是多少?】

答:答案是1。空类型的实例中不包含任何信息,本来求sizeof应该是0,但是当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。至于占多大内存,由编译器决定。(在VS中,每个空类型的实例占1字节的空间)。

<1>如果在该类型中添加一个构造函数和析构函数,再对该类型求sizeof,得到的结果又是多少?

答:还是1。调用构造函数和析构函数只需要知道函数的地址即可,而这些函数的地址只与类型相关,而与类型的实例无关,编译器也不会因为这两个函数而在实例内添加额外的信息。

 

类中六个默认的成员函数--默认:如果用户没有显示提供,编译器生成一份默认的成员函数。

构造函数:

    概念:一个特殊的成员函数,在创建对象时由编译器自动调用,完成对象的初始化工作。

    特性:

  • 函数名与类型相同,没有返回值类型,在创建对象期间由编译器自动调用,并且在对象的生命周期只调用一次。

  • 缺省构造函数:无参构造和全缺省构造,并且只能存在一个。如果用户没有显示提供,编译期将会提供一个;

  • 不能使用static和const修饰,不能是虚函数;

  • 具有初始化列表:初始化类中的非静态成员变量;

  • 作用:构造好初始化对象;

  • 单参构造函数--具有类型转化的作用,禁止:explicit

析构函数、拷贝构造函数、赋值运算符重载------如果没有显式实现:编译器生成默认成员函数(浅拷贝)

static成员 || 对static理解

在C语言中:static变量:全局变量 || 局部变量;

在C/C++,

  • 可以使用static修饰类成员---静态成员;

  • static修饰成员变量---普通成员变量;

  • 是类的属性,不是某个具体的对象;

  • 是所有类型对象共享,不会影响sizeof结果;

  • 在类中只是声明,必须将其放在类外进行初始化,不能将其放在构造函数初始化列表初始化;

  • 访问方式:可以通过对象访问 || 类名::

const成员 || const的理解

在C语言中,const只能修饰变量<这里指不能被修饰的变量>

在C++中,const修饰变量----常量<具有替换>

const修饰类成员:

  • 成员变量:不能在成员函数内部修改,必须在构造函数初始化列表位置进行初始化

构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。例如:

class CExample {public:
int a;
float b;

//初始化列表
CExample(): a(0),b(8.8)
{}

//构造函数内部赋值<构造函数初始化>
CExample()
{
a=0;
b=8.8;
}
};
  • 成员函数:const成员函数,修饰成员函数隐藏你给的this指针;表示:在该成员函数中,不能修改类中的任何非静态的长远变量;【例外:除非该成员变量被mutable修饰】

静态成员函数----普通成员函数

  • 本质:静态成员函数没有隐藏的this指针

  • 调用:对象.静态成员函数 || 类名::静态成员函数

  • 静态成员函数不能访问:非静态的成员变量&&成非静态的员函数

  • 静态成员函数不能使用const修饰

  • 静态成员函数不能为虚函数;

>面向对象和面向过程的区别?

  • 面向过程就是分析出问题解决所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就好了;

举个例子:<五子棋>

面向过程:

  1. 开始游戏

  2. 黑子先走

  3. 绘制画面

  4. 判断输赢

  5. 轮到白子

  6. 绘制画面

  7. 判断输赢

  8. 返回步骤2

  9. 输出结果

面向对象:

  1. 黑白双方

  2. 棋盘系统

  3. 规则系统

面向对象的特点:属性、类

  • 属性:用来描述具体某个对象的特征。面向对象的思想就是把一切都看成对象,而对象一般都有属性(对象静态的一面)+方法(对象动态的一面)组成!

  • 类:具有同种属性的对象称为类,对象就是类的一个实例化;

面向过程与面向对象的优缺点,举一个生活中的常见例子:

  • 用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭;

  • 盖浇饭的好处就是‘菜’‘饭’分离,从而提高了制作盖浇饭的灵活性---‘可维护性好’,‘饭’和‘菜’的耦合性比较低;

  • 蛋炒饭就是将‘蛋’和‘饭’搅拌一起,耦合性很高‘可维护性’比较差。

  • 软件工程最求的目标之一就是可维护性,主要表现在3个方面:可理解性、可测试性、可修改性;

面向过程:

  • 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,较消耗资源,嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素;

  • 缺点:没有面向对象易维护、易复用、易扩展;

面向对象:

  • 缺点:性能比面向过程低;

  • 优点:面向对象易维护、易复用、易扩展,由于面向对象有封装、继承、多态的特性,可以设计出低耦合的系统,使用系统更加灵活、更加易于维护;

>面向对象的三大特性:封装、继承、多态

>c++关键字(98)---63

>命名空间作用:解决命名冲突

>缺省参数:在声明或定义一个函数时,给函数参数设置一个默认值,在调用该函数期间,如果没有传递实参,采用默认值,否则,采用传递的实参

分类:

  1. 全缺省参数--所有参数都带有默认值;

  2. 半缺省参数--部分参数带有默认值(只能从右往左提供);

  3. 注意:半缺省参数只能从右往左依次提供,不能在声明和定义时同时给出;

>函数重载:

  1. 在相同作用中,具有多个相同名称的函数,参数列表必须不同(个数、类型、类型次序),注意:与返回值类型是否相同无关

  2. 调用原理:在编译器阶段,对所传递的实参类型进行推演,根据推演的实际结果去选择调用相对应的类型的函数

>C语言和C++编译器对函数名字修饰规则不同

  1. C语言编译器名字修饰规则:仅仅在函数名谦增加一个_;

  2. C++名字修饰:将类型编译到底层使用的函数名字中;

  3. extern "C":按照C语言的风格来编译函数

>引用:引用就是别名,引用类型变量与其引用的实体共用同一块内存空间

    特性:

  1. 引用在定义时必须初始化,并且不能够改变;

  2. 引用必须同类型;

  3. 非常量引用的初始值必须为左值;

 引用和指针的区别?

  1. 引用在定义时必须初始化,指针没有要求;

  2. 引用在初始化时引用一个实体,就不能在引用其他实体了;而指针可以在任何时候指向任何一个同类型的实体;

  3. 没有NULL引用,但有空指针;

  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节数(32位平台下占4个字节,64位平台下占8个字节);

  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小;

  6. 有多级指针,但是没有多级引用;

  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理;

  8. 引用比指针使用起来更加安全(引用必须判空)

>宏的优缺点:

    优点:

  1. 增强代码的复用性;

  2. 提高性能;

    缺点:

  1. 不方便调试宏;(因为预编译阶段进行了替换)

  2. 导致代码可读性差,容易误用;

  3. 没有类型安全的检查;

C++有哪些技术替代宏?

  1. 常量定义--换成const

  2. 函数定义--换用内联函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值