1. 派生类继承了基类的私有成员,但是不能直接访问,只能通过派生类的友元函数访问。
2. TURBO C中,int占2个字节,long int占4个字节;
union联合体是个省内存的定义方法,里面的day,month,year被定义在一个2字节大小的空间。它的取值完全取决于编程人员最后一次对它的引用。
3. float类型(即IEEE754单精度浮点数格式)能表示的最大整数是:2^128~1^104.
分析:1)阶码 = 指数 + 偏移量,这种阶码表示方式为移码。
2)当阶码E为全0且尾数M也为全0时,表示的真值X为零,结合符号位S为0或1,有正零和负零之分。当阶码E为全1且尾数M也为全0时,表示的真值X为无穷大(∞),结合符号位S为0或1,有+∞和-∞之分。
3)本题中,要除去E用全0和全1(255)表示零和无穷大的特殊情况,因此,阶码E的取值范围变为1~254,而偏移量为127,那么指数范围为-126 ~ +127.
分析二:IEEE754的一些特殊情况,就单精度而言。
32位, 1位符号位+8位指数位+23位小数位
当指数位全部为0,并且小数位全部为0的时候,表示0;通过符号位可以得知是+0,还是-0; 当指数位全部为1,并且小数位全部为0的时候,表示无穷大,计算机里面一般标记为inf;通过符号位可以得知是inf,还是-inf; 当指数位全部为1,并且小数位不全为0的时候,表示这并不是一个有效数,一般即为NaN。
至于本题中的最大数,它的编码形式是这样的 0 1111111011111111111111111111111
4. 1)、一个子类只能继承一个抽象类(虚类),但能实现多个接口;
2)、一个抽象类可以有构造方法,接口没有构造方法;
3)、一个抽象类中的方法不一定是抽象方法,即其中的方法可以有实现(有方法体),接口中的方法都是抽象方法,不能有方法体,只有声明;
4)、一个抽象类可以是public、private、protected、default,接口只有public;
5)、一个抽象类中的方法可以是public、private、protected、default,接口中的方法只能是public和default
在Java中,抽象类中既可以有抽象方法,也可以有普通方法,如果一个类要继承该类,就要重写该类的所有抽象方法。反过来,如果一个方法是抽象方法,那么它必须被定义在抽象类中.而接口中的方法必须是抽象方法,并且没有方法体,程序员可以不显示的写上该方法是抽象方法,但是编译时Java会自动在该方法上加上 public abstract 关键字。
c++虚类,即抽象类,至少有一个抽象方法,可以有方法定义;
java接口,都是抽象方法,对应c++纯虚类;
5. C++函数重载的作用:使用方便,提高可靠性。
1).多个函数共用一个名字,减少对用户的复杂性。
2).函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。
3).类的构造函数跟类名相同,也就是说:构造函数都同名。如果没有函数重载机制,要想实例化不同的对象,那是相当的麻烦!
补充:
1.C++中常量分为6种,它们是整型常量,实型常量,字符型常量,字符串常量,符号常量,逻辑型常量。
2.Private成员只能被本类中的成员函数或者被友元函数访问,子类无法访问。
3.全局对象的生命周期跨越整个程序运行时间,优先于main函数进行初始化,在main函数返回时撤销.即析构。
4.STL中一级容器是指,容器元素本身是基本类型,非组合类型。即vector、deque、list。
STL中的常用容器包括:顺序性容器(vector、deque、list)、关联容器(map、set)、容器适配器(queue、stac)
set,multiset中元素类型是pair<key_type,key_type>;
map,multimap中元素类型是pair<key_type,value_type>;
5.在C++中的结构体是否可以有构造函数。(可以有)
分析:C中的结构体没有函数,但是C++的结构体可以有函数;这是C与C++结构体的区别。
C++的结构体可以被类取代,因为类相对于结构体具有封装性等优势。
C++中结构体与类的区别:结构体中的成员访问权限不声明时候默认是公开的,而类是私有的。struct继承时候默认是public继承。
6.分析下列程序:
#include<iostream>
#include<string>
using namespace std;
class Printer {
public:
Printer(std::stringname) {
std::cout<< name;
}
};
class Container{
public: Container() : b("b"),a("a") {}
Printera; Printer b;
};
int main(){
Container c;
return 0;
}
分析:一直都是ab。
派生类实例化时,先调用基类的构造函数,然后是派生类的类成员变量构造函数(构造的顺序是按照成员变量的定义先后顺序,而不是按照初始化列表的顺序),最后是派生类的构造函数。程序中,先定义了 Printer a;后定义了Printer b;所以输出一定是ab。
初始化列表的初始化顺序与在列表中的顺序无关,由变量在类中定义的先后顺序决定。
11.c++的const函数特点:
1).不能在const函数中修改所在类的对象的数据,因为const函数中的*this是常量,同样只能访问const函数;
2).const函数中只能调用其他的const函数,不能调用非const函数,因为对象调用函数是需要传递对象自己,const函数中的*this是常量,非const函数中的*this是变量,因此不可以调用(除非去除*this的const属性);
Note:使用const_cast后,可以在const函数中调用非const函数的
3).const函数与同名的非const函数是重载函数;
4).const对象只能调用const函数 ,但是非const对象可以调用const函数。
12.给出以下定义,则对两个数组的strlen正确的叙述为:数组x的长度小于等于数组y的长度。
char x[]=”abcdefg”;
char y[]={‘a’,’b’,’c’,’d’,’e’,’f’,’g’};
分析:如果判断数组的长度肯定用strlen()函数,而这个函数以'\0'为结尾判断符,char x[]="abcdefg";定义x数组默认追加结尾符'\0',chary[]={'a','b','c','d','e','f','g'};没有结尾符,strlen(y)的结果是遇到第一个'\0',是一个未定值,因此答案是数组x的长度小于等于y的长度
如果判断数组的大小用sizeof()函数,sizeof()计入数组中包括'\0'在内的所有元素,因此数组x的大小大于数组y的大小,是大小而不是长度。
13.分析下列程序:错误操作。
#include<iostream>
#include<cstdlib>
#include<string.h>
using namespace std;
void getmemory(char *p) {
p=(char*)malloc(100);
strcpy(p,"helloworlld");
}
int main(){
char*str=NULL;
getmemory(str);
printf("%s\n",str);
free(str);
return0;
}
分析:指针指向常量(如char*str=“aaaaa”)和NULL时,不能通过指针修改常量,因为常量本身就是只读的。
退一步来讲,getmemory函数中,p一开始跟str指向同一个位置,经过“p=(char*)malloc(100);”这句话之后p已经指向了动态开辟的空间的首地址,“strcpy(p,"helloworld");”操作针对的是动态开辟的空间,而不是str指向的地址空间了,getmemory函数执行完成后p又自动释放了,所以getmemory函数对str指向的地址空间没有实际的操作。综上可知,str指向的内容未发生变化,故输出NULL。
getmemory函数执行完成后p又自动释放了,这是错的,不用free释放会继续存在,这就是内存泄露。
14. fscanf()作用是从文件流中读取数据,fprintf()是将数据写入到文件。不要搞混。
格式:
int fscanf(FILE*stream,const char*format,[argument...]);
参数:%d:读入一个十进制整数.
%s : 读入一个字符串,遇空字符‘\0'结束。
%c : 读入一个字符。无法读入空值。空格可以被读入。
所以这里是·从文件中读出n个整数到数组a中
15. int main() {
char*p="hello,world";
return0;
}
p和“hello,world”存储在内存的哪个区域?
分析:根据C语言中的特性和定义p是一个局部变量,而C语言中局部变量存在于栈中,"hello,wrold"是一个字符串字面常量,因此存储于程序的只读存储区中,p在这里其实只是指向了"hello,wrold"在只读存储区中的地址而已。
补充:
(1)从静态存储区域分配:
内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量等。
(2)在栈上分配:
在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配:
即动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块。
一个C、C++程序编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区、程序代码区。
16.int x[6][4],(*p)[4];p=x;则*(p+2)指向:x[2][0]
分析:x为二维数组,p是一个数组指针,将p指向长度为4的int数组,那么p指向的元素是x的第一行元素的首个,p+2指的就是第三行的首个元素,所以p[2]所指即为x[2][0]。
17.类成员的缺省访问权限是私有的。
类定义中包括数据成员和函数成员的声明。
18.如下哪个代码不能给地址0xaae0275c赋值为1?(B)
A volatile int *p=(int*)0xaae0275c;*p=1
B (volatile int *)0xaae0275c[0]=1
C volatile int *p=(int*)0xaae0275c;p[0]=1
D *(volatile int*)0xaae0275c[0]=1
分析:主要考察赋值到指定的内存地址
选项A,C通过一个指针向其指向的内存地址写入数据。
选项D,这行代码其实和上面的两行代码没有本质的区别。先将地址0xaae0275c强制转换,告诉编译器这个地址上将存储一个int类型的数据;然后通过钥匙“*”向这块内存写入一个数据。
选项B,将一个右值赋给一个左值,显然行不通。类似指针,int *p; p=1不合理
另外这里涉及到volatile关键字,顺便介绍一下:
(1)用来同步,因为同一个东西可能在不同的存储介质中有多个副本,有些情况下会使得这些副本中的值不同,这是不允许的,所以干脆用volatile,让它只 有一个,没有其他的副本,这样就不会发生不同步的问题。
(2)防止编译器优化去掉某些语句,像我在arm中见到个寄存器非常奇怪,当中断来的时候,相对应的位置1,而清0又不能向这位写0,向这位写1才是1才 是清中断(清0),
// 假设0x560012300 为寄存器地址
#define INTPAND *(volatileunsigned int *)0x560012300
INTPAND = INTPAND; // 清中断
像编译器如果看到有INTPAND = INTPAND;这种看似无用的操作,如果没有volatile说明,编译器就很有可能会去掉INTPAND = INTPAND;实际上有用的东西,却被编译器当没用的东西优化掉了。
(3)当地址是io端口的时候,读写这个地址是不能对它进行缓存的,这是相对于某些嵌入式中有cache才有这个。比如写这个io端口的时候,如果没有这个 volatile,很可能由于编译器的优化,会先把值先写到一个缓冲区,到一定时候 再写到io端口,这样就不能使数据及时的写到io端口,有了volatile说明以后, 就不会再经过cache,write buffer这种,而是直接写到io端口,从而避免了读写 io端口的延时。