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。