错题整理

来源:互联网 发布:贝叶斯网络和神经网络 编辑:程序博客网 时间:2024/06/06 08:58

面向对象的五大基本原则:单一职责原则  开放封闭原则  里氏替换原则   依赖倒置原则   接口隔离原则

int a:3//表示a占3位

模板(template <Ta>)(函数模板/类模板)函数模板:针对仅参数类型不同的函数;类模板:针对仅数据成员和成员函数类型不同的类

#pragma pack(push)//保持对齐状态,设定为push字节对齐

来自class的继承默认按照private继承处理,来自struct的继承默认按照public处理

c里struct只是变量的聚合体,struct不能有函数

c++的struct可有构造和析构函数

运算符优先级:!>算术运算符>关系运算符>&&||>条件运算符>赋值运算符>逗号运算符

floor:向下取整,返回不大于它的最大整数

ceil:向上取整,返回不小于它的最小整数

round:四舍五入,往大数方向入

类定义的外部,一定可以被访问的成员有public

指针就是地址,因此一个变量的指针就是该变量的地址。

for循环的条件判断语句中,如果使用赋值语句或常量值,当值为0时,不执行循环体,当值为非0时,无限循环。

输出a = 10,*p=20(因为常量折叠) 因为a 和p都指向相同的内存地址,所以输出的前两个结果是相同的,但为啥相同的内存里的结果不相同么?--这就是常量折叠.

这个"常量折叠"是 就是在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。可以算作一种编译优化。

因为编译器在优化的过程中,会把碰见的const全部以内容替换掉(跟宏似的: #define pi 3.1415,用到pi时就用3.1415代替),这个出现在预编译阶段;但是在运行阶段,它的内存里存的东西确实改变了!!!

简单的说就是,当编译器处理const的时候,编译器会将其变成一个立即数。

 

在重载某运算符时,若运算符函数的形参表中没有参数,则可能的情况有:该运算符是一个单目运算符。该运算符函数有一个隐含的参数this。该运算符函数是类的成员函数。
 

int *s[8]; //定义一个指针数组,该数组中每个元素是一个指针,每个指针指向哪里就需要程序中后续再定义了。
int (*s)[8]; //定义一个数组指针,该指针指向含8个元素的一维数组(数组中每个元素是int型)。

逗号运算符(百度百科):在C语言中,多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。
所以exec((v1,v2), (v3,v4,v5),v6,v7)相当于exec(v2, v5,v6,v7)。
声明定义函数的时候,exec((v1,v2), (v3,v4,v5),v6,v7)括号内的参数叫做“形式参数”,不是实际的参数变量,是用来接收传递的参数的。而实际调用函数的时候,括号内应该填上对应类型的参数,也就是传递实际参数到函数内,这些参数就是“实参”。
题目问的是“调用”函数时,“实参”的数量,也就是4啦。

  1. 类的静态成员与类直接相关,与对象无关,在一个类的所有实例之间共享同一个静态成员,A正确
  2. 静态成员函数中不能调用非静态成员,C正确
  3. 非静态成员函数中可以调用静态成员,B正确
  4. 常量成员才不能修改,静态成员变量必须初始化,但可以修改(例如我们常利用静态成员变量统计某个函数的调用次数),D错误

 

 

a. 成员函数被重载的特征:

1 )相同的范围(在同一个类中);

2 )函数名字相同;

3 )参数不同;

4 virtual 关键字可有可无。

b. 覆盖是指派生类函数覆盖基类函数,特征是:

1 )不同的范围(分别位于派生类与基类);

2 )函数名字相同;

3 )参数相同;

4 )基类函数必须有 virtual 关键字。

c.“ 隐藏 是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

1 )如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual 关键字,基类的函数将被隐藏(注意别与重载混淆)。

2 )如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

 

 

++的优先级大于*

C++对数组初始化原则是:只要对数组中元素部分初始化,剩余元素都被编译器默认初始化为0.

 

·  int *p[4];  //定义一个指针数组,该数组中每个元素是一个指针,每个指针指向哪里就需要程序中后续再定义了。

int (*p)[4];  //定义一个数组指针,该指针指向含4个元素的一维数组(数组中每个元素是int型)。

 

区分int *p[n]; 和int (*p)[n]; 就要看运算符的优先级了。

int *p[n]; 中,运算符[ ]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组。

int (*p)[n]; 中( )优先级高,首先说明p是一个指针,指向一个整型的一维数组。

1、int (*p)[4]:定义一个数组指针,该指针指向含4个元素的一维数组(数组中每个元素是int型); 2、(int (*)[4])m:表示将m强制转换为大小为4的数组指针;

 

栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将 提示overflow。因此,能从栈获得的空间较小。    
 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储  的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小  受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。 

 

 

If语句中else最近的if进行配对

 

关键字new和malloc都是在堆(heap)上进行动态的内存申请,但是内存释放不同,new申请的内存用delete释放,malloc申请的内存用free释放,因此不能代替

子类重新定义父类的虚函数的方法这种叫覆盖,override

函数不能嵌套定义,也就是函数内部不能定义函数

 

char data[0];请去百度  柔性数组,它只能放在结构体末尾,是

申明一个长度为0的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针!),但对于这个数组的大小,我们可以进行动态分配 请仔细理解后半部分,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!

 对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:

注意:构造缓冲区就是方便管理内存缓冲区,减少内存碎片化,它的作用不是标志结构体结束,而是扩展

柔性数组是C99的扩展,简而言之就是一个在struct结构里的标识占位符(不占结构struct的空间)

(-m)/n 和m/(-n) 等于-(m/n)

m%(-n) 等于m%n

(-m)%n 等于-(m%n)

 

 

explicit构造函数的作用
解析:
explicit构造函数是用来防止隐式转换的。请看下面的代码:

class Test1
{
public:
    Test1(int n)
    {
        num=n;
    }//普通构造函数
private:
    int num;
};
class Test2
{
public:
    explicit Test2(int n)
    {
        num=n;
    }//explicit(显式)构造函数
private:
    int num;
};
int main()
{
    Test1 t1=12;//隐式调用其构造函数,成功
    Test2 t2=12;//编译错误,不能隐式调用其构造函数
    Test2 t2(12);//显式调用成功
    return 0;
}

Test1的构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误。
普通构造函数能够被隐式调用。而explicit构造函数只能被显式调用。
所以此处不能调用参数为int的构造函数。我认为此时编译器应该在所有带参构造函数中寻找适合的。因为上述中的n可以被转换为short,所以选择了参数是short的构造函数。 如果把参数short改为string,编译器就会报错,因为n转换不为string。所以选B

当派生类中不含对象成员时

· 在创建派生类对象时,构造函数的执行顺序是:基类的构造函数→派生类的构造函数;

· 在撤消派生类对象时,析构函数的执行顺序是:派生类的构造函数→基类的构造函数。

当派生类中含有对象成员时

· 在定义派生类对象时,构造函数的执行顺序:基类的构造函数→对象成员的构造函数→派生类的构造函数;

· 在撤消派生类对象时,析构函数的执行顺序:派生类的构造函数→对象成员的构造函数→基类的构造函数。

 

原创粉丝点击