C++学习(32)
来源:互联网 发布:类似日事清的软件 编辑:程序博客网 时间:2024/05/17 23:30
1.
#include<iostream>#include<string.h>using namespacestd;struct A{ int a; char b;}; class B{};class C{ char b[0];};int main() { cout<<sizeof(A)<<""<<sizeof(B)<<" "<<sizeof(C)<<endl; return 0;}
分析:类的实例化是在内存中分配一块地址,每个实例在内存中都有独一无二的二地址。同样,空类也会实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化后就有独一无二的地址了。所以,空类的sizeof为1,而不是0. 多重继承的空类的大小也是1.
2.
#include<iostream>#include<string.h>using namespace std;class A{ public: int_a; A(){ _a=1; } voidprint() { cout<<_a; }}; class B:public A{ public: int_a; B(){ _a=2; }};class C{ charb[0];};int main() { Bb; b.print(); cout<<b._a; return0;}
分析:因为在继承的时候,允许子类存在与父类同名的成员变量,子类会屏蔽父类的成员变量,他们同时存在。 因为给孩子类中没有定义print函数,所以会按照就近原则去寻找父类中是否有print函数。恰好父类中有这个函数,于是调用父类的print函数。所以b.print()这个函数会调用父类的a变量。
子类公有(public)继承父类,所以子类可以通过对象访问父类的公有成员函数,由于调用的是父类的公有成员函数(该函数中的this指针存放的是父类对象的地址),所以打印的是父类A的_a。
3、
C++真正正式公布的标准就三个:C++98、C++03、C++11。
其中C++98是第一个正式C++标准,C++03是在C++98上面进行了小幅度的修订,C++11则是一次全面的大进化(C++0x是C++11标准成为正式标准之前的草案临时名字)。
class foo() {foo(){};};class boo:public foo {boo():foo(){};};
A c++03 B c++0x C c++11 D c++98 E 都不正确
分析:委托构造是对同一类而言,参数类型不同的构造函数可以调用自己的其他构造函数,这个地方就是派生类调用基类的构造,所以并不是委托构造。但是,这个题出了点小插曲,就是foo()在foo类里默认是private的,所以编译时不通过,可能是题目的疏忽。
委托构造函数同一个类的一个构造函数调用另一个构造函数。这道题应该选E,因为根本编译不通过。父类的private构造函数子类无法通过任何方式访问到。
4. Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)。系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思,面向的是硬件。而库函数调用则面向的是应用开发的,相当于应用程序的api。
简明的回答是:函数库调用是语言或应用程序的一部分,而系统调用是操作系统的一部分。
Pwrite是系统调用,而其他的库函数。
fcntl 文件控制
open 打开文件
creat 创建新文件
close 关闭文件描述字
read 读文件
write 写文件
readv 从文件读入数据到缓冲数组中
writev 将缓冲数组里的数据写入文件
pread 对文件随机读
pwrite 对文件随机写
lseek 移动文件指针
_llseek 在64位地址空间里移动文件指针
dup 复制已打开的文件描述字
dup2 按指定条件复制文件描述字
flock 文件加/解锁
poll I/O多路转换
truncate 截断文件
ftruncate 参见truncate
umask 设置文件权限掩码
fsync 把文件在内存中的部分写回磁盘
5.
#include<iostream>#include<string.h>using namespace std;int main() { staticchar*s[]={"black","white","pink","violet"}; char**ptr[]={s+3,s+2,s+1,s},***p; p=ptr; ++p; printf("%s",**p+1); return0;}
6.
#include<iostream>#include<string.h>using namespace std;class B0{ public: virtualvoid display() { cout<<"B0::display"<<endl; }};class B1:public B0{ public: voiddisplay() { cout<<"B1::display0"<<endl; }};class D1:public B1 { public: voiddisplay() { cout<<"D1::display0"<<endl; }}; void fun(B0 ptr) { ptr.display();}int main() { B0b0; B1b1; D1d1; fun(b0); fun(b1); fun(d1); return0;}
分析:此题的关键点在于fun函数,传入的参数是一个类的对象,这样,派生类作为参数传入的时候,会把自动的类型转换为基类对象,这样,display就只是执行基类的函数了。选B0::display() B0::display() B0::display()
void fun(B0 ptr) { ptr.display();}//这里使用的不是按地址传递,程序在这里转化为基类对象,直接调用基类的成员函数。如果是指针传递,改变为B0*ptr,ptr->display(),可以实现多态。
改完后的程序为:
#include<iostream>#include<string.h>using namespace std;class B0{ public: virtualvoid display() { cout<<"B0::display"<<endl; }};class B1:public B0{ public: voiddisplay() { cout<<"B1::display0"<<endl; }};class D1:public B1 { public: voiddisplay() { cout<<"D1::display0"<<endl; }}; void fun(B0 *ptr) { ptr->display();}int main() { B0*b0=new B0; B1*b1=new B1; D1*d1=new D1; fun(b0); fun(b1); fun(d1); return0;}fun(B0 *ptr):使用指针传入结合virtual虚函数,相当于在ptr指针指向的内存空间里边为子类虚函数的实现预留了接口,这样如果传入的是子类,则编译的时候系统会根据子类类别动态加载子类函数;而如果形参不是指针,在编译的时候就不会给子类的虚函数实现留接口,也就无从动态加载子类函数了。另外,如果基函数没有设置函数为virtual类型,同样也不会留接口,不会加载子类函数。
在c++中的继承中,如果基类声明了一个函数为虚函数,那么在派生类中不用声明同名函数为虚函数(不需要加virtual)也可以实现该函数为虚函数。虚函数的动态绑定仅在基类指针或引用绑定派生类对象时发生,fun的形参不是指针,所以调用哪个版本的函数编译时就已经确定,根据形参静态类型确定调用B0的成员。
应通过指针或引用调用虚函数,而不要用对象名调用虚函数。以派生类对象b1赋值给基类对象b0,并调用Display函数,虽然可以编译通过,但Display()函数却是基类B0的函数。C++中一定要用指针或引用来调用虚函数,才能保证多态性的成立。
7.输出数据为:80 8
#include<iostream>#include<string.h>using namespace std;int main() { char*p[10],(*p1)[10];//p是一个指针数组,p1是一个指向“包含10个char变量的数组”的数组指针 cout<<sizeof(p)<<""<<sizeof(p1)<<endl; return0;}分析:重点理解p跟谁结合了,跟[]结合,则p就是一个数组;跟*结合,p就是一个指针;
首先[]()的优先级一样,均大于* char *p[10],p与[]结合,所以p就是一个数组,数组的元素比较特殊,是指针,指针大小为8,所以是10*8=80;
char(*p1)[10],与*结合,所以是一个指针,大小为8;
补充:什么是数组名降级?数组退化?
数组名降级和数组退化是一个概念,它是在某些情况下,对数组的引用会退化为指针。点击打开链接
8.
#include<iostream>#include<string.h>using namespace std;int i=1;class MyCls{ public: MyCls():m_nFor(m_nThd),m_nSec(i++),m_nFir(i++),m_nThd(i++){ m_nThd=i; } void echo() { cout<<"result:"<<m_nFir+m_nSec+m_nThd+m_nFor<<endl; } private: int m_nFir; int m_nSec; int m_nThd; int &m_nFor;};int main() { MyCls oCls; oCls.echo(); return 0;}分析:构造函数中变量的初始化顺序是按其定义的顺序,与初始化列表无关、
首先要明白变量初始化的顺序是其声明的顺序,跟初始化列表中的顺序无关。所以变量的初始化顺序为m_nFir(i++),m_nSec(i++),m_nThd(i++),&m_nFor(m_nThd);
i初始值为1,所以经过初始化列表初始化以后m_nFir=1,m_nSec=2,m_nThd=3,m_nFor为m_nThd的一个引用。
并且此时i的值为4,构造函数中执行语句m_nThd=i后,m_nThd=4,m_nFor是它的一个引用,自然值也为4。
输出结果m_nFir+m_nSec+m_nThd+m_nFor=1+2+4+4=11。
- [C学习]函数(?)
- C#(WINFORM)学习
- C学习(2)
- 学习资源(C++)
- C++&C学习笔记(一)(基础)
- Linux-GCC学习(C/C++)
- C指针学习(Pointers in C)
- c语言学习笔记32
- 学习C语言的相关网站(C学习资料)
- 学习C语言的相关网站(C学习资料)
- 如何学习C++(经典)
- [C学习]总结(数据类型)
- ---------------C#(.NET)学习步骤---------
- C++test 学习(一)
- C++test 学习(二)
- C++test 学习(三)
- C++test 学习(四)
- C++test 学习(五)
- h5+打开淘宝
- Java中常用命令
- [YTU]_2625( 构造函数和析构函数)
- 渐析java的浅拷贝和深拷贝
- handler自己实现
- C++学习(32)
- [UOJ 5]【NOI2014】动物园:KMP
- 关于Android框架模式的浅研究
- ZigBee、WiFi、蓝牙等常用2.4Ghz无线技术的区别
- python爬虫入门
- iOS编程:第三方静态库(.a文件)处理命令
- 如何用SendMessage模拟某一按钮的点击事件
- I/O 多路复用技术是什么
- Java is-a、has-a和like-a、组合、聚合和继承 两组概念的区别