C++重要知识点小结---1
1.C++中类与结构的唯一区别是:类(class)定义中默认情况下的成员是private的,而结构(struct)定义中默认情况下的成员是public的。
2. ::叫作用域区分符,指明一个函数属于哪个类或一个数据属于哪个类。::可以不跟类名,表示全局数据或全局函数(即非成员函数)。
3.类名加载成员函数名之前而不是加在函数的返回类型前。
错误:Tdate::void Set(int m , int d , int y) {}
正确: void Tdate::Set(int m , int d , int y) {}
4.一个类对象所占据的内存空间由它的数据成员所占据的空间总和所决定。类的成员函数不占据对象的内存空间。
5.类的成员函数可以访问该类的private成员。
6.类作用域是指类定义和相应的成员函数定义范围。在该范围内,一个类的成员函数对同一类的数据成员具有无限制的访问权。
7.#include <filename.h> 和#include “filename.h” 有什么区别?
答:
- 对于#include <filename.h> ,编译器从标准库路径开始搜索filename.h
- 对于#include “filename.h”,编译器从用户的工作路径开始搜索filename.h
8.
- int a = 1 , b = 0;
- MAX(a++ , b); //a被增值2次
- MAX(a++ , b + 10); //a被增值1次
MAX(a++ , b)的值为2,同时a的值为3;
MAX(a++ , b + 10)的值为10,同时a的值为2
9.类定义是不分配空间和初始化的。类是一个抽象的概念,并不是一个实体,并不含有属性值,而只有对象才占有一定的空间,含有明确的属性值。
10.运行如下代码:
class A { public: A(int j):age(j) , num(age + 1) //... protected: int num; int age; }; void mian() { A sa(15); }
代码运行结果:num=“随机值 ”, age= 15
由于按成员在类定义中的声明顺序进行构造,而不是按构造函数说明中冒号后面的顺序,所以num成员被赋的是一个随机值,并不是想赋的16,因为这个时候,成员age还没有被赋值,age的内存空间中是一个随机值。
11.如果 const 出现在 * 左边,则指针指向的内容为常量;如果 const 出现在 * 右边,则指针自身为常量;如果 const 出现在 * 两边,则两者都为常量。
- <<effective C++>>上有个好记的方法:const在*号左边修饰的是指针所指的内容;const在*号右边修饰的是指针。
- 简单记就是:左内容,右指针。
我只要一听到被面试者说:"const意味着常数",我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded
Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着"只读"就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:
1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
2). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。
const的用法参考:http://blog.csdn.net/hyg0811/article/details/9349869
12.C++一维数组和指针的关系总结
对于数组int a[10]; a表示数组的第一个元素的地址,即&a[0];
如果使指针p,指向数组的首元素,可以进行操作:int * p=a; 或者int *p=&a[0];
那么p++,是指向数组中的先一个元素,即a[1];
此时*p则是a[1]中所放的值。
此时,a[i]=p[i]=*(a+i)=*(p+i)
关于*p++,由于++和*的优先级相同,结合方向是自右而左,因此它等价于*(p++)。作用是:先得到p指向的变量的值(即*p),然后再使指向p的值加1.
*p++等价于*(p++);而*(++p)表示先使p+1,再取*p。
13.在VC中,sizeof有着许多的用法,而且很容易引起一些错误。下面根据sizeof后面的参数对sizeof的用法做个总结。
A.参数为数据类型或者为一般变量:
例如sizeof(int),sizeof(long)等等。
这种情况要注意的是不同系统系统或者不同编译器得到的结果可能是不同的。
例如int类型在16位系统中占2个字节,在32位系统中占4个字节。
B.参数为数组或指针:
int a[50]; //sizeof(a)=4*50=200;求数组所占的空间大小
int *a=new int[50];// sizeof(a)=4; a为一个指针,sizeof(a)是求指针的大小,在32位系统中,当然是占4个字节。
C.参数为结构或类:
Sizeof应用在类和结构的处理情况是相同的,需要考虑字节对齐(参加另一篇文章:http://www.cnblogs.com/heyonggang/archive/2012/12/11/2812304.html)。另外有几点需要注意:
第一、结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存储位置与结构或者类的实例地址无关。
第二、没有成员变量的结构或类(非虚)的大小为1,因为必须保证结构或类的每一个实例在内存中都有唯一的地址。
第三、包含虚函数的类或者虚继承的类,需要算上虚表指针的占的4个字节。
下面举例说明:
Class Test{int a;static double c};//sizeof(Test)=4.
Test *s;//sizeof(s)=4,s为一个指针。
Class test1{ };//sizeof(test1)=1;
Class test2{ virtual void print(){}};//sizeof(test2)=4;
14.运算符new分配堆内存,如果成功,则返回指向该内存的空间,如果失败,则返回NULL。所以每次使用运算符new动态分配内存时,都应测试new的返回指针值,以防分配失败。
1 Person::Person(Person &p) 2 { 3 cout<<"Copying "<<p.pName<<"into this own book\n"; 4 pName = new char[strlen(p.pName) + 1]; 5 if(pName != 0) 6 strcpy(pName , p.pName); 7 }
15.如果你的类需要析构函数来析构资源,则它也需要一个拷贝构造函数。
由于C++提供的默认拷贝构造函数只是对对象进行浅拷贝复制。如果对象的数据成员包括指向堆空间的指针,就不能使用这种拷贝方式,此时必须自定义拷贝构造函数,为创建的对象分配堆空间。
16.类成员函数的重载、覆盖和隐藏区别?
答案:
a.成员函数被重载的特征:
(1)相同的范围(在同一个类中);(2)函数名字相同;(3)参数不同;(4)virtual 关键字可有可无。
b.覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);(2)函数名字相同;(3)参数相同;(4)基类函数必须有virtual 关键字。
c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
17.《C++程序设计教程》P352
在例子中并没有声明派生类GraduateStudent的构造函数,根据类的实现机制,派生类对象创建时,将执行其默认的构造函数。该默认构造函数会先调用基类的默认构造函数,而基类没有默认构造函数,但正好匹配默认参数的构造函数。
18.在运行时,能根据其类型确认调用哪个函数的能力,称为多态性,或称迟后联编,或滞后联编。编译时就能确定哪个重载函数被调用的,称为先期联编。
多态性可可以简单的概括为“一个借口,多种方法”,在程序运行的过程中才决定调用的函数。
虚函数就是允许被其子类重新定义的成员函数。而子类重新定义父类虚函数的做法,称为“覆盖”或“重写”。
覆盖是指子类重新定义父类的虚函数的做法。
重载是指允许存在多个同名函数,而这些函数的参数表不同。
为了指明某个成员函数具有多态性,用关键字virtual来标志其为虚函数。
如果虚函数在基类与子类中出现的仅仅是名字的相同,而参数类型不同,或返回类型不同,即使写上了virtual关键字,则也不进行迟后联编。
19.一个类中将所有的成员函数都尽可能地设置为虚函数总是有益的。它除了会增加一些资源开销,没有其它坏处。
设置虚函数,需注意下列事项:
- 只有类的成员函数才能说明为虚函数。这是因为虚函数仅适用于有继承关系的类对象,所以普通函数不能说明为虚函数。
- 静态成员函数不能是虚函数,因为静态成员函数不受限于某个对象。
- 内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。即使虚函数在类的内部定义,编译时,仍将其看作非内联的。
- 构造函数不能是虚函数,因为构造时,对象还是一片未定型的空间。只有在构造完成后,对象才能成为一个类的名副其实的实例。
- 析构函数可以是虚函数,而且通常声明为虚函数。
微信公众号:
猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。