C++学习(39)

来源:互联网 发布:java打印心形表白 编辑:程序博客网 时间:2024/06/18 01:49

1.抽象类是不完整的,它只能用作基类。在面向对象方法中,抽象类主要用来进行类型隐藏和充当全局变量的角色。

 

抽象类具有以下特性

1)抽象类不能实例化。

2)抽象类可以包含抽象方法和抽象访问器。

3)不能用sealed修饰符修饰抽象类,因为这两个修饰符的含义是相反的。采用sealed 修饰符的类无法继承,而abstract修饰符要求对类进行继承

4)从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。

 

2.下列程序分析:

void fun(B0 ptr){  ptr.display();}
分析一:此处使用的不是按地址传递,这样转化为基类对象,直接调用基类成员函数,如果是指针传递,改为B0 *ptr,ptr->display(),可以实现多态、

 

分析二:

虚函数的动态绑定仅在基类指针引用绑定派生类对象时发生,fun的形参不是指针,所以调用哪个版本的函数编译时就已经确定,根据形参静态类型确定调用B0的成员。

 

fun(B0 *ptr)

使用指针传入结合virtual虚函数,相当于在ptr指针指向的内存空间里边为子类虚函数的实现预留了接口,这样如果传入的是子类,则编译的时候系统会根据子类类别动态加载子类函数

而如果形参不是指针,在编译的时候就不会给子类的虚函数实现留接口,也就无从动态加载子类函数了。

另外,如果基函数没有设置函数为virtual类型,同样也不会留接口,不会加载子类函数。

 

3

C静态函数不可以是虚函数

因为静态成员函数没有this,也就没有存放指针的地方,同时其函数的指针存放也不同于一般的成员函数,其无法成为一个对象的虚函数的指针以实现由此带来的动态机制。静态是编译时期就必须确定的,虚函数是运行时期确定的。

D虚函数可以声明为inline

inline函数和virtual函数有着本质的区别,inline函数是在程序被编译时就展开,在函数调用处用整个函数体去替换,而virtual函数是在运行期才能够确定如何去调用的,因而inline函数体现的是一种编译期机制virtual函数体现的是一种运行期机制

因此,内联函数是个静态行为,而虚函数是个动态行为,他们之间是有矛盾的。

函数的inline属性是在编译时确定的, 然而,virtual的性质则是在运行时确定的,这两个不能同时存在,只能有一个选择,文件中声明inline关键字只是对编译器的建议,编译器是否采纳是编译器的事情。并不否认虚函数也同样可以用inline来修饰,但你必须使用对象来调用,因为对象是没有所谓多态的,多态只面向行为或者方法,但是C++编译器,无法保证一个内联的虚函数只会被对象调用,所以一般来说,编译器将会忽略掉所有的虚函数的内联属性

 

相关知识点:什么函数不能声明为虚函数

一个类中将所有的成员函数都尽可能地设置为虚函数总是有益的。

设置虚函数须注意:

1):只有类的成员函数才能说明为虚函数

2):静态成员函数不能是虚函数;

3):内联函数不能为虚函数;

4):构造函数不能是虚函数;

5):析构函数可以是虚函数,而且通常声明为虚函数

 

4.用关键字virtual修饰的成员函数叫做虚函数,虚函数是为了实现多态而存在的,必须有函数体纯虚函数的声明,是在虚函数声明的结尾加=0,没有函数体。在派生类中没有重新定义虚函数之前是不能调用的。

 

纯虚函数的实现必须在派生类中。(可以给抽象类中的纯虚函数提供定义。比如 析构函数声明为纯虚函数后必须给它提供一个定义,定义就是指给它一个函数体。)

 

如果一个类中至少含有一个纯虚函数,此时称之为抽象类。所以抽象类一定有纯虚函数

基类类型的指针可以指向任何基类对象或派生类对象

 

5.sizeof是C语言中的一个操作符(operator),不是函数调用,简单的说其作用就是返回一个对象或者类型所占的内存字节数由于结果是无符号整数,因此可以把它看作是无符号整型表达式

 

6.’\0‘的ASCAll码为0,所以NULL等效于0

 

7一个浮点数由三部分组成:符号位S、指数部分E(阶码)以及尾数部分M

单精度浮点数(float)总共用32位来表示浮点数,其中尾数用23位存储,加上小数点前有一位隐藏的1(IEEE754规约数表示法),2^(23+1)=16777216因为10^7<16777216<10^8,所以说单精度浮点数的有效位数是7。考虑到第7位可能的四舍五入问题,所以单精度最少有6位有效数字(最小尺寸)。

 

同样地:双精度浮点数(double)总共用64位来表示浮点数,其中尾数用52位存储,2^(52+1)=9007199254740992,10^16<9007199254740992<10^17,所以双精度的有效位数是16。同样四舍五入,最少15位。

 

补充:单精度浮点数的有效位数是7位。

双精度浮点数的有效位数是16位。

 

8.声明一个指向含有10个元素的数组的指针,其中每个元素是一个函数指针,该函数的返回值是int,参数是int*,表达式是:

int (*(*p)[10])(int *);

 

分析:先看未定义标识符p,p的左边是*,*p表示一个指针,跳出括号,由于[]的结合性大于*,所以*p指向一个大小为10的数组,即(*p)[10]。左边又有一个*号,修释数组的元素,*(*p)[10]表示*p指向一个大小为10的数组,且每个数组的元素为一个指针。跳出括号,根据右边(int *)可以判断(*(*p)[10])是一个函数指针,该函数的参数是int*,返回值是int。

 

分析二:首先题目说要声明一个数组指针,一般我们想到的数组指针是随便来一个int(*p)[10],然后又说每个元素是一个函数指针,那么我们随便来一个函数指针int(*pf)(int *)。然后把(*p)[10]作为一个整体替代pf即int(*(*p)[10]))(int *);分析:判断一个复杂式子看最高优先级的,*p是一个指针,然后(*p)外面是[],所以是数组指针,(*p)[10])描述完毕,然后再看外面int(*)(int *)很明显,这是一个函数指针,所以这个数组中每个元素是函数指针

 

9. A预处理是 C语言程序从源代码变成可执行程序的第一步,主要是C语言编译器对各种预处理命令进行处理,包括头文件的包含、宏定义的扩展、条件编译的选择等。

 

B: 编译之前,C语言编译器会进行词法分析、语法分析 (-fsyntax-only) ,接着会把源代码翻译成中间语言,即汇编语言。编译程序工作时,先分析,后综合,从而得到目标程序。所谓分析,是指词法分析和语法分析;所谓综合是指代码优化,存储分配和代码生成。值得一提的是,大多数的编译程序直接产生机器语言的目标代码,形成可执行的目标文件,但也有的编译程序则先产生汇编语言一级的符号代码文件,然后再调用汇编程序进行翻译加工处理,最后产生可执行的机器语言目标文件。

 

C:链接是处理可重定位文件,把它们的各种符号引用和符号定义转换为可执行文件中的合适信息(一般是虚拟内存地址)的过程。

 

编译时只是把函数的符号地址记录下来;链接时该函数符号有定义才会变成具体的地址。如果链接过程中所有符号都有定义,链接成功,生成可执行文件;否则链接失败。


//预处理:处理#include、宏替换和条件编译//编译:生成目标文件(.cpp->.o)//链接:链接多个目标文件//例子://main.cppint main() {  fun();} //编译不可通过,提示函数fun()未声明void fun();int main(){ fun(); } //编译可通过,链接不可通过,提示函数fun()未定义

点击打开链接

 

10.在VS2010中,实际测试循环
for(inti=10,j=1;i=j=0;i++,j--)
执行0次。在计算机中,0代表false,1或其他代表true。因此在判断i=j=0时,判断条件为false,不进入循环内部。

 

11. 位域表示法

C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,

允许其它类型类型的存在。

使用位域的主要目的是压缩存储,其大致规则为:

1)如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

2)如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;(经测试此条好像仅限于char型,整型可以跨域存储)

3)如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方

式,Dev-C++采取压缩方式;

4)如果位域字段之间穿插着非位域字段,则不进行压缩;

5)整个结构体的总大小为最宽基本类型成员大小的整数倍。

 

12. i=0时,共有两个进程: 主进程和主进程创建的第一个进程

i=1时,以上两个进程分别创建新的进程,此时共有四个进程

i=2时,以上四个进程分别创建新的进程,此时共有8个进程

....

依次类推, 当i=n时,共创建2^(n+1)个进程

点击打开链接

 

13. free指的是释放该指针所指向的内存资源,指针值没有变化,为了防止指针成为野指针,需要在free后将指针置为NULL。

 

free之后的指针仍然指向原来的堆地址,即仍然可以继续使用,但很危险。因为操作系统已经认为这块内存可以使用,它会毫不考虑的将他分配给其他程序,于是你下次不小心使用到该指针(野指针)时,如果操作系统及时制止了这种行为,报错(非法操作),然后将你的程序杀掉,给你很容易改正错误的机会,这还算比较好的结果!如果操作系统没有制止这种行为,那么产生的后果可就说不准了,说不定整个操作系统会崩溃,那么你再来改正这个错误,就不容易发现咯!所以,最好free了以后再置空,即令指针=NULL;,表示本程序已经放弃再使用该指针。

 点击打开链接

 

14.无论是static还是非static的全局变量,如果不加限制随意访问的话易出现同步问题。
无论是static还是非static的局部变量,每个线程都是私有的,其他线程不会对其进行干扰。

 

原创粉丝点击