1.函数原型声明时,是忽略形参的名字的,形参只起到注释的作用,函数原型声明的另一个作用就是强制类型转换,实参数据类型会自动转换成形参的数据类型,这个类型转换必须符合c语言的类型提升规则,否则会导致数值变化。
2.按值调用和按引用调用
3.auto和register用于声明自动存储周期的变量,局部变量默认是自动存储周期,register只能用在自动存储周期的变量上,但有时编译器在编译程序的时候可能会忽略register声明,例如:在没有足够多的寄存器空间时。事实上,今天的编译器已经有很好的优化功能,自己就会去找被频繁访问的变量,,并将其驻留在寄存器中,无需借助register声明。
4.数组初始化:如果初始化列表提供的初始值个数少于数组拥有的元素个数,则余下的数组元素将被初始化为零,自动数组不能自动的初始化为零,你至少要将第一个数组元素初始化为零,另外,初始化数组时,如果提供的初始化值个数多余数组所包含元素的个数,将会出现语法错误。静态数组在编译时会自动进行初始化,如果没有显式的初始化一个静态数组,那么他的元素会被编译器自动初始化为零。
5.数组传递给函数,指定不带放括号的数组名即可,与包含字符串的字符数组不同,其他类型数组没有一个特殊的结束符,因此调用函数时必须将数组所包含的元素个数也传递给被调函数,这样被调函数才能正确数目的数组元素。
C语言自动以传地址的方式把数组传递给被调函数——即被调函数能够修改主调函数的原数组,当在表示数组的形参前面加上类型限定符const后,相应数组的元素值将在函数体内保持不变。若函数体内出现任何试图修改数组元素的操作,都将导致一个编译时错误。si
6.sizeof 是一个编译时运行的运算符,所以不会导致运行时开销。
7.对于指针算数而言,加上或减去一个整数时,指针的增减值是这个整数乘以指针所指对象的字节数,这个字节数取决于对象的数据类型。例如,指针vPtr为3000,所以vPtr +=2;,当vPtr指向的是4字节的整型时,得到的结果是3008,如果是2字节的整型那么结果就是3004;
同理,如果两个指针做减法,得出的是两个指针之间的数组元素个数,例如,vPtr和v2Ptr都指向一个4字节的整型数组,vPtr的值为地址3000,v2Ptr的值为地址3008,则x=v2Ptr-vPtr,x为2,除非是在数组上执行,否则指针的算数运算无意义。
8.字符串拷贝函数strncpy,不会将表示字符串结束的空字符写入数组,所以需要程序单独将‘/0’写入到数组中。
9.一个结构体不能包含他自身的实例,但是可以包含指向自身结构体类型的的指针类型成员。
10.指针/下标表示法,指针可以像数组那样用下标的形式来引用,例如,指针变量bPtr指向数组b,那么bPtr[1]就是指b【1】。
数组名实质上就是一个常量指针,是不能改写所代表的值的,例如,*(b+3)正确,但是b+=3,是无效的。
11.结构体成员运算符“.”,结构体指针运算符“->”。
12.结构体和共用体的定义不会产生变量,只是定义了一种变量类型。
13.使用malloc时,一定要检测他的返回值是否为NULL指针。如果分配内存没有成功,则打印一条出错信息。
C++部分
1.C++ 中如果实参和形参类型不一致,那么编译器会报错。
2.函数重载通常用于创建几个对不同类型数据进行相似操作的同名函数,编译器会根据实参类型选择调用最合适的函数。
3.当使用cin和流读取运算符读取数据时,如果出现空格,便会停止读取。因此要输入完整的带空格的数据时应使用 getline(cin,nameOfCourse);
4.尽量通过get和set函数来访问和操作类的数据成员,这样,改变数据成员的名字或者数据类型只会影响相应的get和set函数,而不会影响调用 他们的函数。修改是规则而不是异常,程序员应该遇见到代码会经常被修改。
5.默认的构造函数不初始化类的数据成员。如果类的数据成员是其他类的对象,则默认构造函数会隐式的调用每个数据成员的默认构造函数,以确保正确初始化数据成员。
6.定义构造函数时,可以用类里的函数来进行初始化。
7.尽管函数原型中的形参名是任意的(编译器忽略这些形参名),很多程序员仍使用形参名以便于编写文档,一般复制对应函数定义的第一行语句,然后末尾加上分号,建立函数原型。
8.用预处理命令#ifndef ,#define ,和#endif 形成一个预处理包装,防止头文件多次包含在一个程序中。
9.强烈推荐在类的构造函数中初始化数据成员(基本类型的数据成员没有默认初始化),只有整型或enum类型的static const数据成员可以在类体中初始化。
10.如果成员函数在类体中定义,则c++编译器就会尝试(just尝试)内联该成员函数的调用,编译器保留内联任何函数的权利,只有简单的和稳定的(即实现不太可能改变)成员函数应该在类的头文件中定义。
11.对类名或类对象应用sizeof运算符时,只会返回类的数据成员规模,因为编译器只创建一份独立于该类的所有对象的成员函数的副本。类的所有对象共享这一份副本,因为各个对象的数据是不同的,所以每个对象需要自己的数据副本。
12.类的成员函数可以重载,但是只能被该类的其他成员函数重载(不同形参集合)。
13.指针定义的时候最好把*放在指针类型那一边,例如count* countptr 而不是count *countptr,可以在定义的时候初始化,count* counterptr =&counter;
14.如果类的成员函数已经提供了构造函数所需的所有或者部分功能,则在构造函数中调用该成员函数,可以简化代码,避免重复代码,但是由于构造函数用于对对象进行初始化,数据成员可能还没在一致状态,在数据成员未被初始化之前就使用它们可能导致逻辑错误。
15.析构函数没有形参也没有任何返回值。
16.返回一个private数据成员的引用或指针会破坏类的封装性,使得客户代码依赖于类的数据表示。因此,返回private数据指针或者引用是危险的,应尽量避免。
17.类中包含指向动态分配内存的指针类型的数据成员时,拷贝构造函数可能导致严重的错误。
18.C++编译器不允许对const对象调用成员函数,除非成员函数本身也被声明为const,此外,不允许声明为const的成员函数修改对象,构造函数和析构函数通常都需要修改对象,不允许将构造函数和析构函数声明为const,必须允许构造函数修改对象,才能正确初始化对象。非const对象可以调用非const和const成员函数,但是const对象只能调用const对象。
19.const数据成员和引用数据成员必须用成员初始化值初始化,因为不能通过赋值修改const对象,所以必须初始化对象。
20.对于所有的继承形式而言,基类的private成员都不能被该类的派生类直接访问,但是这些private基类成员仍然是被继承的(即他们仍然被认为是派生类的一部分),通过这些从基类继承来的成员,派生类可以操作基类的private成员,但是友元不会被继承。
21.使用protect数据成员的两个主要问题:1.派生类对象不必用成员函数设置基类的protected数据成员的值,因此派生类很容易给protected数据成员赋无效值,是对象处于不一致状态。2.派生类成员函数很容易依赖于基类的实现,实际上,派生类应该只依赖于基类的服务(即非private成员函数),而不依赖于基类的实现,否则基类中一个很小的改变则可能破坏派生类的实现。
22.成员函数将基类数据成员声明为private可使程序员在修改基类实现时不必修改派生类的实现。
23. 利用虚函数和多态,程序员可以用通用的方法处理程序,而让执行环境处理特殊情况。
24.基类指针可以指向基类对象和派生类对象,派生类指针只能指向派生类对象,编译器只允许基类指针调用基类成员函数,如果基类指针指向了派生类对象,并且试图访问只属于派生类的成员函数,则会产生编译错误。指针所调用成员函数的功能取决于该函数的句柄类型(即指针和引用的类型),而不取决于句柄所指向的对象类型。而调用对象的功能不调用句柄类型的功能就是多态。
25.如果不将基类中的函数声明为virtual,则可以重新定义该函数,如果基类中的函数声明为virtual,则可以重写该函数,支持多态行为。
26.通过指向派生类对象的基类指针调用虚函数,程序就会动态的根据对象的类型选择适当的派生类函数,在运行时选择调用正确的函数称为动态绑定或者后期绑定。当通过对象名和点成员选择运算符调用虚函数时,该函数调用是在编译时解析的,这称为静态绑定,,这时所调用的虚函数是对象所属类中定义的函数,这不是多态行为,只有使用指针句柄时才会发生虚函数的动态绑定。
27.基类指针和派生类指针指向基类对象和派生类对象的四种方式:
1.直接将基类指针指向基类对象
2.直接将派生类指针指向派生类对象
3.将基类指针指向派生类对象,这种指针只能调用基类的成员函数。如果将基类指针强制转换成派生类指针,就可以使用基类指针调用派生类对象的所有功能。
4.将派生类指针指向基类对象,这会导致编译错误。
28.利用多态性进行编程可以实现等价switch逻辑
29.由于抽象类通常用做继承层次结构中的基类,所以也称为抽象基类,抽象基类的用途是为其他类提供一个适当的可供继承的基类。由于抽象基类过于通用,因而不能定义具体的对象,如果要实例化对象,则需要为其提供更为确切的定义。
30. 将类定义成抽象类的方法是将该类中一个或多个虚函数声明为纯虚函数,若在基类中给出某个函数的实现是没有意义的,但需要具体派生类实现该函数时,可将该函数声明为纯虚函数。抽象类至少有一个纯虚函数,抽象类也可以有数据成员和具体函数(包括构造函数和析构函数)。
31.在基类中已经定义的虚函数,在整个类层次结构中会一直保持虚函数属性,良好的变成习惯是在层级结构的每个层次中将这样的函数声明为虚函数会使程序更加清晰。
32.c++中不允许直接将基类指针赋给派生类指针。
33.构造函数不能声明为虚函数,否则是编译错误。如果一个类中有虚函数,则无论如何是否需要析构函数都应该为该类提供一个虚析构函数。这是因为该类的派生类可能包含必须被正确调用的析构函数。?