C++小题(十三)

/*
#include命令的功能是()。
正确答案: C   

在命令处插入一个头文件
在文件首部插入一个头文件
在命令处插入一个文本文件
在文件首部插入一个程序文件

预处理器发现#include后,就会寻找指令后面<>中的文件名,并把这个文件的内容包含到当前的文件中,
被包含的文件中的文本将替换源代码文件中的#include指令
*/
//
/*
下列选项,不正确的是

正确答案: B   你的答案: B (正确)

A for(int a=1;a<=10;a++);

B int a=1;
do
{
a++;
}while(a<=10)

C int a=1;
while(a<=10)
{
a++;
}

D for(int a=1;a<=10;a++)a++;

do循环以后的while后面必须要有分号“;”
*/
//
/*
如果有一个类是 myClass , 关于下面代码正确描述的是:

myClass::~myClass(){
delete this;
this = NULL;
}
正确答案: C   你的答案: B (错误)

a正确,我们避免了内存泄漏
b它会导致栈溢出
c无法编译通过
d这是不正确的,它没有释放任何成员变量。

this指针内容为const,不允许进行修改,故this = NULL编译不成功。
*/
//
/*
如下程序:

#include "stdio.h"
class Base
{
public:
    Base()
    {
        Init();
    }
    virtual void Init()
    {
        printf("Base Init\n");
    }
    void func()
    {
        printf("Base func\n");
    }
};
class Derived: public Base
{
public:
    virtual void Init()
    {
        printf("Derived Init\n");
    }
    void func()
    {
        printf("Derived func\n");
    }
};
 
int main()
{
    Derived d;
    ((Base *)&d)->func();
     
    return 0;
}
该程序的执行结果
正确答案: B   你的答案: B (正确)
a
Base Init				
Derived func
b
Base Init
Base func
c
Derived Init			
Base func
d
Derived Init
Derived func

在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。
显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,
如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,
所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。
但是不是说你不可以那么写程序,你这么写,编译器也不会报错。
只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。

在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,
然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,
会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。
*/
//
/*
下列关于赋值运算符“=”重载的叙述中,正确的是

正确答案: A   你的答案: A (正确)

赋值运算符只能作为类的成员函数重载
默认的赋值运算符实现了“深层复制”功能
重载的赋值运算符函数有两个本类对象作为形参
如果己经定义了复制拷贝构造函数,就不能重载赋值运算符
*/
//
/*
在C++中,下列不正确的转义字符是( )
正确答案: B   你的答案: B (正确)

A'\\'
B'074'
C'\t'
D'\0'

A 转义字符,就是反斜线字符\
B 错误,内容是3个字符,如果是'\074'则是正确的8进制转义 '\074'才是转义字符
C 跳到下一制表区
D 字符串的末尾
*/
//
/*
重复多次 fclose 一个打开过一次的 FILE *fp 指针会有什么结果?
正确答案: A   你的答案: A (正确)

A导致文件描述符结构中指针指向的内存被重复释放,进而导致一些不可预期的异常
B不会出现异常,释放一个已经释放的指针,系统会自动忽略
C运行异常
D以上答案都不正确

 fclose是一个函数名,功能是关闭一个流。使用fclose()函数就可以把 缓冲区 内最后剩余的数据输出到内核缓冲区,
 并释放 文件指针 和有关的缓冲区。 函数原型:int fclose( FILE *fp ).
一次正常的fclose会争取释放FILE指针的相关内容。再次fclose释放已经释放掉了的FILE指针,所以会出错
函数fclose()不会判断指针是否null
*/
//
/*
若要重载+、=、<<、=和[]运算符,则必须作为类成员重载的运算符是

正确答案: D   你的答案: D (正确)

A+和=
B=和<<
C==和<<
D=和[]

解释:
          (1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
          (2)单目运算符最好重载为成员函数。
          (3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
          (4) 对于其它运算符,建议重载为友元函数。
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。
也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:
          函数类型 operator 运算符名称 (形参表列)
          { 
          对运算符的重载处理
          }
重载为类成员函数时参数个数=原操作数个数-1(后置++、--除外)
重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参
*/
//
/*
内联可能会寻致二进制可执行文件尺寸变大吗?
正确答案: A   你的答案: A (正确)

是
错

假设系统有100个内联函数,每个展开后有100字节,并且被调用了100次。这就会增加1MB的大小 
*/
//
/*
下面的程序的输出是什么?

#include<stdio.h>
 
int main(void)
{
 int n;
 char y[10] = "ntse";
 char *x = y;
 n = strlen(x);
 *x = x[n];
 x++;
 printf("x=%s\n",x);
 printf("y=%s\n",y);
 return 0;
}

正确答案: B   你的答案: B (正确)

x=atse,y=
x=tse,y=
x=atse,y=e
x=tse,y=e

n = strlen(x),此时n=4,因为x指向y数组,所以x[4]就是y[4]='\0',
那么*x=x[n]就是把x指向的字符串首元素改为'\0',x++之后x指向第二个字符t,
所以第一个输出x=tse,而y遇到第一个字符就是'\0',所以结束,y输出为空
*/
//
/*
下列说明中 const char *ptr;ptr应该是()
正确答案: C   你的答案: C (正确)

指向字符常量的指针;
指向字符的常量指针;
指向字符串常量的指针;
指向字符串的常量指针;
*/
//
/*
代码执行后,a和b的值分别为?

class Test{
public:
    int a;
    int b;
    virtual void fun() {}
    Test(int temp1 = 0, int temp2 = 0)
    {
        a=temp1 ;
        b=temp2 ;
    }
    int getA()
    {
        return a;
    }
    int getB()
    {
        return b;
    }
};
 
int main()
{
    Test obj(5, 10);
    // Changing a and b
    int* pInt = (int*)&obj;
    *(pInt+0) = 100;  
    *(pInt+1) = 200;  
    cout << "a = " << obj.getA() << endl;
    cout << "b = " << obj.getB() << endl;
    return 0;
}
正确答案: A   

200 10
5 10
100 200
100 10

指向虚函数表的指针在32位系统下占用4个字节,其地址分布在整个类成员变量的地址的首部,
接下来就是变量a的地址、b的地址。当将test对象obj赋给指向整型的pInt后,
指针pInt指向了地址的首部也就是虚函数表指针,所以*(pInt+0)=100改变的是虚函数表的值,
接下来*(pInt+1)=200改变的是变量a的值,变量b没有变换。
*/
//
/*
关于static用途说法确的是?
正确答案: B C D   你的答案: B C D (正确)

声明静态外部类
声明静态全局变量
声明静态函数
声明静态局部变量

1:设置静态局部变量,变量只定义一次,不能被别的函数使用
2:设置静态全局变量,变量不能被外部文件所使用
3:在类中设置静态函数,只能访问静态变量
*/
//
/*
在为传统面向对象语言的程序做单元测试的时候,经常用到mock对象。Mock对象通过反射数。请问反射最大程度破坏了面向对象的以下哪个特性?
正确答案: A   你的答案: A (正确)

封装
多态
继承
抽象

mock对象:也成为伪对象,在测试中的利用mock对象来代替真实对象,方便测试的进行。
封装性:指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,通过该类提供的方法实现对内部信息的操作访问。
反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性
*/
//
/*
表头文件

include<stdio.h>
定义函数

int fgetc(FILE * stream);
函数说明

fgetc()从参数stream所指的文件中读取一个字符,并把它作为一个字符返回。若读到文件尾或出现错误时,它就返回EOF,你必须通过ferror或feof来区分这两种情况。
返回值

fgetc()会返回读取到的字符,若返回EOF则表示到了文件尾,或出现了错误。
*/
//
/*
下面关于虚函数的描述,错误的是
正确答案: B   你的答案: B (正确)

在成员函数声明的前面加上virtual修饰,就可把该函数声明为虚函数
基类中说明了虚函数后,派生类中对应的函数也必须说明为虚函数
虚函数可以是另一个类的友元函数,但不能是静态成员函数
基类中说明的纯虚函数在其任何需要实例化的派生类中都必须实现
*/
//
/*
以下函数用法正确的个数是:

void test1()
{
    unsigned char array[MAX_CHAR+1],i;
    for(i=0;i<=MAX_CHAR;i++){
        array[i]=i;
    }
}
char*test2()
{
    char p[] = "hello world";
    return p;
}
char *p =test2();
void test3(){
    char str[10];
    str++;
    *str='0';
}
正确答案: A   你的答案: A (正确)

0
1
2
3

第一个问题:
重点不在于CHAR_MAX的取值是多少,而是在于i的取值范围是多少。
一般char的取值范围是-128到127,而u char 则是0~255,所以i的取值范围是0~255.
所以当CHAR_MAX常量大于255时,执行i++后,i不能表示256以上的数字,所以导致无限循环。

第二个问题:
重点在于函数中p的身份,他是一个指针,还是数组名;
如果是指针p,则p指向存放字符串常量的地址,返回p则是返回字符串常量地址值,调用函数结束字符串常量不会消失(是常量)。
所以返回常量的地址不会出错。
如果是数组p,则函数会将字符串常量的字符逐个复制到p数组里面,返回p则是返回数组p,但是调用函数结束后p被销毁,里面的元素不存在了。
例子中p是数组名,所以会出错,p所指的地址是随机值。
若是把char p[]="hello";改成char *p="hello";就可以了。

第三个问题:
重点在于str++;这实际的语句就是str=str+1;而str是数组名,数组名是常量,所以不能给常量赋值。(可以执行str+1,但是不能str=.)
*/
//
/*
在c++中,
const int i = 0; 
int *j = (int *) &i; 
*j = 1; 
printf("%d,%d", i, *j)
输出是多少?
正确答案: A   你的答案: A (正确)

0,1
1,1
1,0
0,0
C++中的常量折叠:指const变量(即常量)值 放在编译器的符号表中 ,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化.
想要修改i的值可以: 
	const volatile int i = 0; 
	int *j = (int *) &i; 
	*j = 1; 
	printf("%d,%d", i, *j);
	则输出1,1 
*/
//
/*
下面程序段的输出结果是:

int a = 5, b = 4, c = 3, d = 2;
    if (a>b>c)
        printf("%d\n", d);
    else if ((c - 1 >= d) == 1)
        printf("%d\n", d + 1);
    else
        printf("%d\n", d + 1);
正确答案: B   你的答案: B (正确)

2
3
4
编译错误

*/
//
/*
下面关于数组的初始化正确的是:
正确答案: B   你的答案: B (正确)

char str[2] = {"a","b"};
char str[2][3]={"a","b"};
char str[2][3]={{'a','b'},{'e','d'},{'e','f'}};
char str[] = {"a", "b"}; 
*/
//
/*
struct T {
    char a;
    int *d;
    int b;
    int c:16;
    double e;
};
T *p;
在64位系统以及64位编译器下,以下描述正确的是
正确答案: C   你的答案: C (正确)

sizeof(p) == 24
sizeof(*p) == 24
sizeof(p->a) == 1
sizeof(p->e) == 4
缺省对齐下三条准则
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
以上都是结构体中只有基本类型时的缺省对齐方式,当有嵌套复合成员时,
【2】改为:复合成员相对于结构体首地址偏移量是复合成员最宽基本类型大小的整数背

 P为指针,64位系统地址占8个字节
 根据内存对齐  32字节  a_ _ _ _ _ _ _ | * d  8字节|  | b4字节|  |c2字节|_ _ |e8字节|
 正确
double 8字节 
*/
//
/*
类B从类A派生,则类B可以访问类A中的( )成员?
正确答案: A C   你的答案: A C (正确)

public成员
private成员
protected成员
数据成员
函数成员
*/
//
/*
下面关于数组的描述错误的是:
正确答案: C D   

在C++语言中一维数组的名字就是指向该数组第一个元素的指针
长度为n的数组,下标的范围是0-n-1
数组的大小必须在编译是确定
数组只能通过值参数和引用参数两种方式传递给函数
*/
//
/*
如果x=2014,下面函数的返回值是()
int fun(unsigned int x)
{
     int n=0;
     while((x+1))
     {
         n++;
         x=x|(x+1);
     }
     return n;
}

正确答案: C   你的答案: C (正确)

20
21
23
25
x&(x-1)统计1的个数,x|(x+1)统计0的个数
*/
//
/*
int a[3][4],下面哪个不能表示 a[1][1]?
正确答案: C   你的答案: C (正确)

*(&a[0][0]+5)
*(*(a+1)+1)
*(&a[1]+1)
*(a[1]+1)
*/
//
/*
在Windows 32位操作系统中,假设字节对齐为4,对于一个空的类A,sizeof(A)的值为()?
正确答案: B   你的答案: B (正确)

0
1
2
4

类的实例化是在内存中分配一块地址,每个实例在内存中都有独一无二的二地址。
同样,空类也会实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化后就有独一无二的地址了。
所以,空类的sizeof为1,而不是0. 多重继承的空类的大小也是1.
*/
//
/*
下列关于一个类的静态成员的描述中,不正确的是
正确答案: D   你的答案: D (正确)

A该类的对象共享其静态成员变量的值
B静态成员变量可被该类的所有方法访问
C该类的静态方法只能访问该类的静态成员变量
D该类的静态数据成员变量的值不可修改

静态方法里只能访问本类方法中的静态成员,不能直接访问非静态的属性和方法。
这是因为静态方法不依赖于对象,所以当类加载成功后,静态方法就可以访问了。
而此时的对象不一定存在,非静态成员自然也不一定存在。
而且即使存在非静态成员,静态方法也不知道访问哪一个对象的成员。
静态方法中也不能出现this关键字,因为this是针对对象而言的。
本类中的非静态方法可以访问本类的静态属性,也可以调用静态方法。
*/
//

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值