1 没有初始化的变量的初始值
具有 “静态” 生存期的未初始化变量 (即, 在函数外声明的变量和有静态存储类型的变量) 可以确保初始值为零, 就像程序员键入了 “=0” 一样。因此, 这些变量如果是指针会被初始化为正确的空指针, 如果是浮点数会被初始化为 0.0 (或正确的类型)
具有 “自动” 生存期的变量 (即, 没有静态存储类型的局部变量) 如果没有显示地初始化, 则包含的是垃圾内容。对垃圾内容不能作任何有用的假设。这些规则也适用于数组和结构 (称为 “聚合体” ); 对于初始化来说, 数组和结构都被认为是 “变量”。
用 malloc() 和 realloc() 动态分配的内存也可能包含垃圾数据, 因此必须由调用者正确地初始化。用 calloc() 获得的内存为全零, 但这对指针和浮点值不一定有用
2 面向对象的三大特征
面向对象的三大特征是封装性、继承性和多态性:
(1) 封装性:将客观事物抽象成类,每个类对自身的数据和方法实行 protection(private, protected,public)。
(2) 继承性:广义的继承有三种实现形式:实现继承(使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。
(3) 多态性:是将父类对象设置成为和一个或更多它的子对象相等的技术。用子类对象给父类对象赋值之后,父类对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
多态作用:A ) 隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;B)接口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。
说明:面向对象的三个特征是实现面向对象技术的关键,每一个特征的相关技术都非常的复杂
面向对象可以理解成对待每一个问题,都是首先要确定这个问题由几个部分组成,而每一个部分其实就是一个对象。然后再分别设计这些对象,最后得到整个程序。传统的程序设计多是基于功能的思想来进行考虑和设计的,而面向对象的程序设计则是基于对象的角度来考虑问题。这样做能够使得程序更加的简洁清晰。
说明:编程中接触最多的“面向对象编程技术”仅仅是面向对象技术中的一个组成部分。发挥面向对象技术的优势是一个综合的技术问题,不仅需要面向对象的分析,设计和编程技术,而且需要借助必要的建模和开发工具。
构造函数不能是虚函数。而且不能在构造函数中调用虚函数,因为那样实际执行的是父类的对应函数,因为自己还没有构造好。
析构函数可以是虚函数,而且,在一个复杂类结构中,这往往是必须的。析构函数也可以是纯虚函数,但纯虚析构函数必须有定义体,因为析构函数的调用是在子类中隐含的。
说明:虚函数的动态绑定特性是实现重载的关键技术,动态绑定根据实际的调用情况查询相应类的虚函数表,调用相应的虚函数。
3 C++的空类的成员函数
class Empty
{
};
// 虽然Empty类定义中没有任何成员,但是为了一些默认的操作,编译器会加入以下成员函数,使得类的对象拥有通用的功能
class Empty
{
public:
Empty(); //缺省构造函数
Empty(const Empty& ); //拷贝(复制)构造函数
~Empty(); //析构函数
Empty& operator=( const Empty& ); //赋值运算符
Empty* operator&(); //取址运算符
const Empty* operator&() const; //取址运算符 const
};
缺省拷贝构造函数。
缺省析构函数。
缺省赋值运算符。
缺省取址运算符。
缺省取址运算符 const。
注意:有些书上只是简单的介绍了前四个函数。没有提及后面这两个函数。但后面这两个函数也是空类的默认函数。另外需要注意的是,只有当实际使用这些函数的时候,编译器才会去定义它们。
4 拷贝构造函数和赋值运算符
拷贝构造函数和赋值运算符重载有以下两个不同之处:
(1)拷贝构造函数生成新的类对象,而赋值运算符不能。
(2)由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新建对象相同。而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中有内存分配要先把内存释放掉
注意:当有类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算符,不要使用默认的。
5 类成员函数的重写、重载和隐藏的区别
(1)重写和重载主要有以下几点不同。
· 范围的区别:被重写的和重写的函数在两个类中,而重载和被重载的函数在同一个类中。
· 参数的区别:被重写函数和重写函数的参数列表一定相同,而被重载函数和重载函数的参数列表一定不同。
· virtual 的区别:重写的基类中被重写的函数必须要有 virtual 修饰,而重载函数和被重载函数可以被virtual 修饰,也可以没有。
(2)隐藏和重写、重载有以下几点不同。
· 与重载的范围不同:和重写一样,隐藏函数和被隐藏函数不在同一个类中。
· 参数的区别:隐藏函数和被隐藏的函数的参数列表可以相同,也可不同,但是函数名肯定要相同。当参数不相同时,无论基类中的参数是否被 virtual 修饰,基类的函数都是被隐藏,而不是被重写。
说明:虽然重载和覆盖都是实现多态的基础,但是两者实现的技术完全不相同,达到的目的也是完全不同的,覆盖是动态态绑定的多态,而重载是静态绑定的多态。
6 链表和数组的区别
数组和链表有以下几点不同:
(1)存储形式:数组是一块连续的空间,声明时就要确定长度。链表是一块可不连续的动态空间,长度可变,每个结点要保存相邻结点指针。
(2)数据查找:数组的线性查找速度快,查找操作直接使用偏移地址。链表需要按顺序检索结点,效率低。
(3)数据插入或删除:链表可以快速插入和删除结点,而数组则可能需要大量数据移动。
(4)越界问题:链表不存在越界问题,数组有越界问题。
说明:在选择数组或链表数据结构时,一定要根据实际需要进行选择。数组便于查询,链表便于插入删除。数组节省空间但是长度固定,链表虽然变长但是占了更多的存储空间。
7 队列和栈的异同
队列和栈都是线性存储结构,但是两者的插入和删除数据的操作不同,队列是“先进先出”,栈是“后进先出”。
注意:区别栈区和堆区。堆区的存取是“顺序随意”,而栈区是“后进先出”。栈由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。堆一般由程序员分配释放, 若程序员不释放,程序结束时可能由 OS 回收。分配方式类似于链表。
它与本题中的堆和栈是两回事。堆栈只是一种数据结构,而堆区和栈区是程序的不同内存存储区域。