首页 > 程序人生 > 程序员面试技艺 > 百度校园招聘C++类笔试题及答案解析
2014
11-11

百度校园招聘C++类笔试题及答案解析

一、选择题

 1.下列关于对象初始化的叙述中,正确的是:

 A. 定义对象的时候不能对对象进行初始化

 B. 定义对象之后可以显式地调用构造函数进行初始化

 C. 定义对象时将自动调用构造函数进行初始化

 D. 在一个类中必须显式地定义构造函数实现初始化

答案:C(对象在定义时会自动调用构造函数进行初始化)

2.下列关于基类和派生类关系的叙述中,正确的是:

A. 每个类最多只能有一个直接基类

B. 派生类中的成员可以访问基类中的任何成员

C. 基类的构造函数必须在派生类的构造函数体中调用

D. 派生类除了继承基类的成员,还可以定义新的成员

答案:D

3.下列关于赋值运算符“=”重载的叙述中,正确的是:

A. 赋值运算符只能作为类的成员函数重载

B. 默认的赋值运算符实现了“深层复制”功能

C. 重载的赋值运算符函数有两个本类对象作为形参

D. 如果己经定义了复制(拷贝) 构造函数,就不能重载赋值运算符

答案:A

4.下列选项中,正确的C++标识符是

A. 6_group   B. group~6     C. age+3     D. _group_6

答案:D

5. 下列循环语句中有语法错误的是

A.  int i;for( i=1;i<10;i++)cout<<‘*‘

B.  int i,j;for(i=1,j=0;i<10;i++,j++)cout<<‘*‘

C.  int i=0;for(;i<10;i++)cout<<‘*‘

D. for(1)cout<<‘*‘

答案:D. 其他三个都能正常运行

6. 下列定义语句中,错误的是

A int px*   B. char *acp[10]    C. char(*pac)[10]  D. int(*p)()

答案:A。A明显编译不过;B定义了一个数组;C定义了一个指针pac,它指向含有10个char型元素的数组首地址;D定义了函数指针p,这个指针指向的函数无参数且返回一个int值。

7. 若MyClass为一个类,执行“MyClass a[4],*p[5];”语句时会自动调用该类构造函数的次数是

A. 2     B. 5     C. 4      D. 9

答案:C。a[4]定义了4个元素的数组,数组里存的是MyClass对象,故要调用默认的构造函数来初始化4个MyClass对象,*p[5]定义了5个元素的数组,数组中存放的是指向MyClass对象的指针,故没有实例化MyClass对象。

写个小程序验证一下:

#include <iostream>
using namespace std;
class myClass{
    public:
    myClass(){
        cout<<"constructor called..."<<endl;
    }
};
int main(){
    myClass a[4],*p[5];
    cout<<sizeof(a)/sizeof(myClass)<<endl;
    cout<<sizeof(p)/sizeof(myClass)<<endl;
    cout<<sizeof(*p)/sizeof(myClass)<<endl;
    system("pause");
    return 0;
}

这里a数组的大小其实也是4(因为空类占有大小为1字节),p的大小为20字节,因为每个指针占有4字节,*p里面是指针,故大小为4字节。

8. 有如下程序:

#include<iostream>
#include<cmath>
using std::cout;
classPoint{
    public:friend double distance(const Point &p); //p距原点的距离
    Point(int xx=0,int yy=0):x (xx),Y(YY){}//①
    private:int x,Y;
};

double distance(const Point &p) { //②
    return sqrt(p.x*p.x+p.Y*p.Y);
}
int main(){
    Point p1(3,4);
    cout<<distance(p1); //③
    return 0;
}

下列叙述中正确的是:

A. 程序编译正确   

B. 程序编译时语句①出错

C. 程序编译时语句②出错   

D. 程序编译时语句③出错

答案:A. 经过验证,程序编译正确。

9. 下列哪两个是等同的

 int b;

1). const int *a =&b;

2). const * int a = &b;

3). const int*const a = &b;  

4). int const* const a = &b;

答案:3和4相同。 1定义一个指针a,它指向一个整型的不变量,即不能通过a来修改b的值(但b的值是可以修改的)。2编译错误。3和4均定义的指针它本身就不可改变(不能再把另外的变量地址赋值给它),它指向的变量也不可通过它来修改。

10. 有如下语句序列:

char str[10];

cin>>str;

当从键盘输入”I lovethis game”时,str中的字符串是:

A. "I love this game"    B. "I love thi"     C. "I love"     D. "I"

答案:D。str的地址是数组的首地址,也就是str[0],故字符串中只有一个字符I

11. 有函数模板声明和一些变量定义如下:

template<class Tl,class T2,class T3>T1 sum(T2,T3);

double dl,d2;

则下列调用中,错误的是

A. sum<double,double,double>(dl,d2);  

B. sum<double;double>(d1,d2);

C. sum<double>(d1,d2);   

D. sum(d1,d2);

答案:D. D会导致编译错误,因为编译器无法去匹配参数列表。

12. 以下程序段完全正确的是

A. int*p; scanf("%d",&p)

B. int *p; scanf(“%d”,p)

C. int k,*p=&k; scanf("%d",p)

D. int k,*p:; *p= &k; scanf(“%d”,p)

答案:A、C。

A项编译能通过,也能运行,定义了一个指针p,并给这个指针赋值(输入的是地址);B项中指针p的值没有定义,此时它没有指向任何内存地址,故通过它来给对应的内存地址输入变量是错误的。C正确,通过p来给k赋值。D编译不过,语句*p=&k错误。

13. 有定义语句:int *p[4];以下选项中与此语句等价的是:

A. int p[4];     B. int **p;     C. int *(p[4]);      Dint (*p)[4];

答案:C。D项定义了一个指针p,它指向有4个整型元素的数组。

14. 若要重载+、=、<<、=和[]运算符,则必须作为类成员重载的运算符是

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

答案:D。A中+可以为友元,B中<<可以为友元,C中==和<<均可以为友元

15. 下列说法正确的是:

A. 内联函数在运行时是将该函数的目标代码插入每个调用该函数的地方

B. 内联函数在编译时是将该函数的目标代码插入每个调用该函数的地方

C. 类的内联函数必须在类体内定义

D. 类的内联函数必须在类体外通过加关键字inline定义

答案:B

16. 下面对于友元函数描述正确的是:

A. 友元函数的实现必须在类的内部定义

B. 友元函数是类的成员函数

C. 友元函数破坏了类的封装性和隐藏性

D. 友元函数不能访问类的私有成员

答案:C

17. 在公有派生情况下,有关派生类对象和基类对象的关系,下列叙述不正确的是:

A. 派生类的对象可以赋给基类的对象

B. 派生类的对象可以初始化基类的引用

C. 派生类的对象可以直接访问基类中的成员

D. 派生类的对象的地址可以赋给指向基类的指针

答案:C。其它都是多态的特性。

18. 下列关于多态性的描述,错误的是:

A. C++语言的多态性分为编译时的多态性和运行时的多态性

B. 编译时的多态性可通过函数重载实现

C. 运行时的多态性可通过模板和虚函数实现

D. 实现运行时多态性的机制称为动态绑定

答案:C。模版是编译时的多态。

19. 如果友元函数重载一个运算符时,其参数表中没有任何参数则说明该运算符是:

A. 一元运算符     B.二元运算符     C. 选项A 和选项B 都可能     D. 重载错误

答案:D。 C++中用友元函数重载运算符至少有一个参数,重载一目运算符要有一个参数,重载二目运算符要有两个参数。

20. 在下列关于C++函数的叙述中,正确的是:

A. 每个函数至少要有一个参数 

B. 每个函数都必须返回一个值

C. 函数在被调用之前必须先声明 

D. 函数不能自己调用自己

答案:C

21. 如果进栈序列为el,e2,e3,e4,则可能的出栈序列是:

A. e3,el,e4,e2     B. e2,e4,e3,el     C. e3,e4,e1,e2     D. 任意顺序

答案:B。排除法

22. 下面关于模板的描述,错误的是:

A. 函数模板和类模板的参数可以是任意的数据类型

B. 类模板不能直接使用,必须先实例化为相应的模板类,然后定义了模板类的对象

C. 函数模板不能直接使用,需要实例化为模板函数后才能使用

D. 类模板的成员函数都是模板函数

答案:A

解析:参数不能是任意类型的,至少该有明确的类型,比如抽象类就不行。D中可能有些疑惑:

类模版的成员函数有两种情况:

1)涉及模板参数T的一定是个个函数模板;

2)不涉及(形式上,函数体,参数表内没出现)模板参数T的也是个函数模板;

角度一:成员函数的类型中包含一个属性“属于什么类”,所以void A<T>::fun(){};这是就和T建立了联系,这时就能说明即使函数体内不涉及T类型,它也是个函数模板,因为由不同T类型,是不同的函数类型(因为域概念是成员函数类型的一部分)。

23. 下面对静态数据成员的描述中,正确的是:

A. 静态数据成员可以在类体内进行初始化

B. 静态数据成员不可以被类的对象调用

C. 静态数据成员不受private控制符的作用

D. 静态数据成员可以直接用类名调用

答 案:D。B明显不对。A其实有点歧义,一般来说静态成员是在类中声明,类外定义初始化,但当静态成员是const int时是可以直接在类内部进行初始化的(此时还是要在类外部声明一下)。C也是有歧义的,静态变量的初始化时不受private作用,可以在类外进行初 始化,但之后引用修改就不行了。

24. 对类成员访问权限的控制,是通过设置成员的访问控制属性实现的,下列不是访问控制属性的是:

A. 公有类型     B.私有类型     C. 保护类型     D.友元类型

答案:D

25. 抽象基类是指:

A. 嵌套类       B. 派生类      C.含有纯虚函数       D. 多继承类

答案:C

26.如果已定义了一个C++类CMyList并有以下语句:

CMyList list(3);

以下说法正确的是:

A. 该语句会创建一个CMyList类的一个对象;

B. 该语句会创建一个CMyList类的3个对象;

C. 必须为类CMyList定义一个构造函数;

D. 必须为类CMyList定义一个析构函数;

E. 必须定义函数CMyList list(int);

答案:C。必须定义参数为int类型的构造函数,否则编译不通过。

27. 以下说法正确的是:

A. 内联(inline)函数改善了函数调用的执行效率

B. 类A的友元(friend)函数可以访问类A的私有成员

C. 类A的友元(friend)类B可以访问类A的私有成员

D. 类A的静态数据成员为类A的所有对象所共享

E. 类A的静态成员函数没有传递this 指针作为参数

答案:A,B,C,D,E

28.类B从类A派生,则类B可以访问类A中的:

A. public成员      B. private成员      C. protected成员      D. 数据成员      E.函数成员

答案:A,C

29. 面向对象的程序设计语言具有()等共同特性:

A. 封装性      B. 多态性      C.简单性      D.复杂性      E.继承性

答案:A,B,E

30. 现有一个程序如下:

class A{
    public:
    void f(){
        cout<<"A::f().."<<endl;
    }
};
class B{
    public:
    void f(){
        cout<<"B::f().."<<endl;
    }
    void g(){
        cout<<"B::g().."<<endl;
    }
};
class C:public A,public B{
    public :
    void g(){
        cout<<"C::g().."<<endl;
    }
    void h(){
        cout<<"C::h().."<<endl;
        f();// 语句1
    }
};
int main(){
    C obj;
    obj.f();//语句2
    obj.A::f();//语句3
    obj.B::f();//语句4
    obj.g(); //语句5
    system("pause");
    return 0;
}

则编译时会产生错误的语句有:

A. 语句1      B. 语句2      C. 语句3      D. 语句4      E.语句5

答案:A,B

二、填空题

1.

int func(x){
    int countx = 0;
    while(x){
        countx ++;
        x = x&(x-1);
    }
    return countx;
}

假定x = 9999。 函数的运行结果为:8

分析:该函数功能是计算一个数x二进制表示中1的个数:x&(x-1)计算后x每次少一个1。

2. 一个栈的初始状态为空。首先将元素5,4,3,2,1 依次入栈,然后退栈一次,再将元素A,B,C,D依次入栈,之后将所有元素全部退栈,则所有元素退栈(包括中间退栈的元素)的顺序为:1DCBA2345

3. 一棵二叉树有10个度为1的结点,7个度为2的结点,则该二叉树共有25个结点。

分析:在二叉树 度为二的节点数=度为一的节点+1

4. 一个双目运算符作为类的成员函数重载时,重载函数的参数表中有1个参数。

分析:作为类的成员函数时,会传入代表本对象的this指针,从而省去了一个参数

5. #define DOUBLE(x) x+x ,i= 5*DOUBLE(5); i的值为30

分析:宏定义只是简单的展开替换,不作处理

6. switch()中不允许的数据类型是:除整型和字符型外的其他类型都不允许

7. 某32位系统下, C++程序void *p = malloc( 100 ); sizeof (p) = 4

分析:32位机上,各种类型的指针均为4字节。

8. int a = 4;(++a) += a;执行后a的值为10

分 析:先做a的自增,a值变为5(修改了内存地址中的值,等式两边均变为5),相加为10;(a++) +=a是不合法的,因为a已经做了自增,此时还要返回a原先的值,并要用这个值和等号右边的a值(已经自增过了)做运算,自然不合法。(++a) += a++ 执行完后,a值为11,相当于再做一次自增。

9. 派生类中的成员函数可以直接访问基类中的公有成员和保护成员。

10. C++语言的参数传递机制包括传值和传引用两种。

三、阅读题

1.写出函数Test的运行结果:

void Test(void){
    char *str = (char *) malloc(100);
    strcpy(str,"hello");
    // cout<<str<<" "<<*str<<endl;
    free(str);
    if(str!= NULL){
        strcpy(str,"world");
        printf(str);
    }
}

分析:程序会崩溃。因为free函数释放了str所指的内存,但指针值此时不为NULL,故if块中的语句会执行,导致试图将对一块儿不合法的内存写入数据。所以一般调用完free函数释放完空间后应将指针显示赋值为NULL。

2.写出程序的运行结果:

#include <iostream>
using namespace std;
class Base{
    int x;
    public:
    Base(int b):x(b){}
    virtual void display(){
        cout<<x<<endl;
    }
};
class Derived:public Base{
    int y;
    public:
    Derived(int d):Base(d),y(d){}
    void display(){
        cout<<y<<endl;
    }
};
int main(){
    //Test();
    Base b(1);
    Derived d(2);
    b.display();
    d.display();
    Base *p=&d;
    p->display();
    //Base *q=new Derived;
    system("pause");
    return 0;
}

程序输出:

1

2

2

3.下面的函数实现在一个固定的数上加上一个数,有什么错误,改正

int add_n(int n) { static int i=100; i+=n; return i;}

分析:题目的意思有点儿不太明了,固定的数是指每次都给100上加一个指定的值吗?这样的话要去掉static关键字。

4.i最后等于多少?

int i = 1;

int j = i++;

if((i>j++) && (i++ == j)) i+=j;

分析:i为5,j为2 。

5.

#include <iostream>

using namespace std;
constint SIZE=10;

class stack{
    char stck[SIZE];
    int top;
    public:
    void init();
    void push(char ch){
        char pop();
    };
    void stack::init(){ 
        top=0; 
    }
    void stack:push(char ch){
        if(top==SIZE){
            cout<<”Stack is full.\n”;
            return ;
        }
        stck[top++]=ch;
    }
    char stack:pop(){
        if(top==0){
            cout<<”Stack is empty.\n”;
            return 0; 
        }
        return stck[--top];
    }
}
void main(){
    stack s1, s2;
    s1.init();
    s2.init();
    s1.push(‘a’);
    s1.push(‘b’);
    s1.push(‘c’);
    s2.push(‘x’);
    s2.push(‘y’);
    s2.push(‘z’);
    for(int i=0; i<3; i++) 
        cout<<”Pop s1:”<< s1.pop();
    for(i=0; i<3; i++) 
        cout<<”Pop s2:”<< s2.pop();
}

分析:输出cbazyx

四、附加题

写一个Singleton。Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

C++代码:

class Singleton{
    private:
    static Singleton *instance;
    Singleton(){cout<<"Singleton example";}
    public:
    static Singleton* getSingleton(){
        if(instance==NULL){
            instance=new Singleton();
        }
        return instance;
    }
};
Singleton * Singleton::instance=NULL;

注意两点:

1.构造函数为私有,防止直接实例化。

2.指针为静态变量

编程技巧