C++学习(62)

来源:互联网 发布:ambr软件 编辑:程序博客网 时间:2024/06/05 21:00

1 C语言允许函数值尅下缺省定义,此时该函数值隐含的类型是整型。

 

2. 预定义的操纵算子

使用成员函数控制格式化输入输出时,每个函数调用需要写一条语句,尤其是它不能用在插入或提取运算符的表达式中,而使用操纵算子,则可以在插入和提取运算符的表达式中控制格式化输入和输出。在程序中使用操纵算子必须嵌入头文件iomanip.h

 

C++提供了大量的用于执行格式化输入/输出的流操纵算子。流操纵算子提供了许多功能,如设置域宽、设置精度、设置和清除格式化标志、设置域填充字符、刷新流、在输出流中插入换行符并刷新该流、在输出流中插入空字符、跳过输入流中的空白字符等等。

 

3. (1)不允许重载的运算符有:分量运算符 点号, 成员对象选择 点星号, 作用域解析 双冒号, 条件运算符 问号冒号。

不能重载‘.’,因为‘.’在类中对任何成员都有意义,已经成为标准用法。不能重载?:,因为这个运算符对于类对象来说没有实际意义,相反还会引起歧义。还有::。

(2)Const对象是常对象,不改变成员变量的值,而成员函数中只有const函数可以确保不改变成员变量的值,只能调用const类型成员函数。

(3)析构函数一般定义为虚函数,构造函数不能是虚函数。

(4)重载只要求函数名相同,参数类型和个数不同,不要求返回值类型。

 

4.

#include<iostream>using namespacestd;class A{       public:              virtual ~A(){              };              virtual void FunctionA(){              };}; class B{       public:              virtual void FunctionB(){              };}; class C:publicA,public B {       public:};int main(){       C aobject;       A * pa=&aobject;       B * pb=&aobject;       C * pc=&aobject;       cout<<pa<<""<<pb<<" "<<pc<<endl;}


输出结果:0x28fe8c             0x28fe90          0x28fe8c

子类的指针和第一个基类的指针是一样的,和第二个基类指针是不同的。

Pb和pa的差值是虚函数表指针的大小,32位机器是4字节,64位机器是8字节。

 

补充:为什么我输出 pB == pC是否相等,输出的结果为true, 你可以试试,输出的地址情况,和你的类似,

cout<<pb<<""<<pc<<" "<<(pb==pc)<<endl;       int *b=(int*)pb;       int *c=(int*)pc;       cout<<b<<""<<c<<" "<<(b==c)<<endl;


分析:这个会有上行转换的,你判断派生类类型的指针pc会隐式转换成基类类型指针。这个时候就相等了。

 

每个父类一个虚表,子类的虚函数放在第一个父类虚表的最后。

 

http://blog.csdn.net/haoel/article/details/3081328/

多重继承时,以声明顺序在内存中存储A/B的空间(即虚表+数据),再存储C的数据;C中重新实现的虚函数会在A/B的虚表中取代原有的虚表项,C中新加的虚函数会加在A中虚表的最后。

 

5. 1).printf("-\n");对于行输出/n有清除缓存的作用;
2).fork()可以复制父进程的缓存,变量值等信息;
3).i=0时,父进程A产生一个子进程A1,此时输出两行“-”;
4).i=1时,fork使父进程A产生子进程A2,A1产生子进程A3,此时A-A3共产生4行“-”(因为现在A,A1的输出行缓冲均为空); 
总数为6:2(A)+2(A1)+1(A2)+1(A3)=6;
对比

点击打开链接
由于A2,A3会继承A和A1的输出行缓冲区,所以会分别输出两个“-”,加起来为:2(A)+2(A1)+2(A2)+2(A3)=8;

 

int i; for(i=0;i<2; i++){ fork(); printf("-"); }

1).fork()系统调用是Unix下以自身进程创建子进程的系统调用,一次调用,两次返回,如果返回是0,则是子进程,如果返回值>0,则是父进程(返回值是子进程的pid),这是众为周知的。

2).还有一个很重要的东西是,在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令,变量值,程序调用栈,环境变量,缓冲区,等等。

所以,上面的那个程序为什么会输入8个“-”,这是因为printf(“-“);语句有buffer,所以,对于上述程序,printf(“-“);把“-”放到了缓存中,并没有真正的输出,在fork的时候,缓存被复制到了子进程空间,所以,就多了两个,就成了8个,而不是6个。

 

而本题printf("-\n");

程序遇到“\n”,或是EOF,或是缓中区满,或是文件描述符关闭,或是主动flush,或是程序退出,就会把数据刷出缓冲区。需要注意的是,标准输出是行缓冲,所以遇到“\n”的时候会刷出缓冲区,但对于磁盘这个块设备来说,“\n”并不会引起缓冲区刷出的动作,那是全缓冲,你可以使用setvbuf来设置缓冲区大小,或是用fflush刷缓存。

 

6.广义表L=(a,(b,c)),进行Tail(L)操作后的结果为:((b,c))

 

 7.

#include<iostream>using namespacestd;struct S{       int n;       char c[10];}*p;int main(){       struct S a[3]={{3,"abc"},{5,"def"},{7,"ghi"}};       p=a;       printf("%d,",(*p).n);       printf("%d\n",(++p)->n);// 如果把括号去掉,运算结果就会变成4.因为成员选择符->优先级比前置++、后置++都要高。       printf("%d\n",(a++)->n);       //printf("%d\n",(p++)->n);// p++->n中加括号"(p++)->n"或者不加括号,运算结果都是3。       //printf("%d\n",(p+1)->n);}

分析:《C专家编程》中讲过,++a是取a的地址,增加它的值,再写入寄存器中,而a++是取a的地址,将它的值装入寄存器,再增加它的值。因此可以解释为什么C选项加不加括号结果都一样。

原创粉丝点击