题目摘录-编程语言(C++)(四)

Q 31 :

题目:
    分析一下这段程序的输出:
    #include<iostream>
    using namespace std;
    class B{
    public:
        B(){
            cout << "default constructor" << " ";
        }
        ~B(){
            cout << "destructed" << " ";
        }
        B(int i):data(i){
            cout << "constructed by parameter" << data << " ";
        }
    private:
        int data;
    };
    B Play(B b){
        return b;
    }
    int main(int argc, char *argv[]){
        B temp = Play(5);
        return 0;
    }

答案:
    constructed by parameter5
    destructed
    destructed

解答:
    考察赋值运算顺序以及拷贝构造函数。
    1. B temp = Play(5)从右向左执行。
    2. 先将"5"转为形式参数B的类型,之后调用B(int i)打印
"constructed by parameter"。
    4. B temp调用B的默认浅拷贝构造函数,完成赋值,由于拷贝构
造函数没有输出,所以没有打印东西。
    6. Play()生命周期结束后,b析构打印"destructed"。
    7. main()生命周期结束后,temp析构打印"destructed"。

Q 32 :

题目:
    int i=10, j=10, k=3;
    k*=i+j;
    k最后的值是?

答案:
    60

解答:
    考察运算符优先级。
    1. +优先级高于*=,等价于k = k * (i +j)。

Q 33 :

题目:
    #include命令的功能是:

答案:
    在命令处插入一个文本文件

解答:
    1. "#include"在命令处插入,插入文本过程为预处理过程。

Q 34 :

题目:
    有一个类A,其数据成员如下:
    class A {
    private:
        int a;
    public:
        const int b;
        float* &c;
        static const char* d;
        static double* e;
    };
    则构造函数中,成员变量一定要通过初始化列表来初始化的是:

答案:
    b
    c

解答:
    考察构造函数初始化列表的使用。
    构造函数中,成员变量一定要通过初始化列表来初始化的有以
    下几种情况:
        const常量成员:因为常量只能在初始化,不能赋值,所以必
        须放在初始化列表中。
        引用类型:引用必须在定义的时候初始化,并且不能重新赋值,
        所以也要写在初始化列表中。
        没有默认构造函数的类类型:因为使用初始化列表可以不必
        调用默认构造函数来初始化,而是直接调用拷贝构造函数。

Q 35 :

题目:
    在一个64位的操作系统中定义如下结构体:
    struct st_task{
        uint16_t id;
        uint32_t value;
        uint64_t timestamp;
    };
    同时定义fool函数如下:
    void fool(){
        st_task task = {};
        uint64_t a = 0x00010001;
        memcpy(&task, &a, sizeof(uint64_t));
        printf("%11u, %11u, %11u", task.id, 
        task.value, task.timestamp);
    }
    上述fool()程序的执行结果为:

答案:
    1
    0
    0

解答:
    考察结构体对齐。
    1. 假设低地址在低位,最低16 bits被赋给低16位的id变量。
    2. 接下来16 bits的0x0001部分被赋值给了pading部分,没有被使用。
    3. value和timestamp均未被赋值。

Q 36 :

题目:
    在32位系统中:
    char arr[] = {4, 3, 9, 9, 2, 0, 1, 5};
    char *str = arr;
    sizeof(arr) = (1);
    sizeof(str) = (2);
    strlen(str) = (3);
答案:
    8;4;5

解答:
    考察指针和数组名使用sizeof时区别及转义字符。
    1. 数字0对应'\0'。
    2. strlen求字符串长到'\0'前。

Q 37 :

题目:
    下面代码输出什么:
    #include<stdio.h>
    int main( ){
        unsigned int a = 6;
        int b = -20;
        (a + b > 6) ? printf(">6") : printf("<=6");
        return 0;
    }

答案:
    >6

解答:
    考察强制类型转换。
    1. 必须先明确:int与unsigned相加,int -> unsigned int。
    2. int b = -20,首位位"1",用无符号型表示是非常大的正整数。

Q 38 :

题目:
    对于下面的C语言声明描述正确的一项是:
    char (*p)[16]

答案:
    p是指向长度为16的字符数组的指针

解答:
    考察运算符优先级。
    1. p先和那个运算符结合就是什么。
    2. char *p[16]:p是一个包含16个元素的Char型指针数组,
    []优于*,p[]先结合,是数组。
    3. char (*p)[16]:p是一个指针,指向一个包含16个元素的
    char数组,由于()出现,先和*结合,是指针。

[Q 39]

题目:
    下面程序输出结果是什么:
    #include<iostream>
    using namespace std;
    class A{
    public:
        A(char *s){
            cout << s << endl;
        }
        ~A(){}
    };
    class B:virtual public A{
    public:
        B(char *s1, char*s2):A(s1){
            cout << s2 << endl;
        }
    };
    class C:virtual public A{
    public:
        C(char *s1, char*s2):A(s1){
            cout << s2 << endl;
        }
    };
    class D:public B, public C{
    public:
        D(char *s1, char *s2, char *s3, char *s4):
        B(s1, s2), C(s1, s3), A(s1){
            cout << s4 << endl;
        }
    };
    int main() {
        D *p = new D("class A", "class B", "class C",
         "class D");
        delete p;
        return 0;
    }

答案:
    class A
    class B
    class C
    class D

解答:
    考察虚继承的继承顺序。
    1. class B, class C为虚继承。
    2. 虚继承(class 派生类:virtual 继承方式 基类名):从不
    同的路径继承过来的同名数据成员在内存中就只有一个拷贝。
    3. 继承顺序:
        执行基类构造函数,多个基类的构造函数按照被继承的顺序构
        造。
        执行成员对象的构造函数,多个成员对象的构造函数按照声明的顺序构造。
        执行派生类自己的构造函数。
    4. 要执行D构造函数必须先执行参数列表,欲构造B, C必须先构
    造A,其B, C虚继承A,所以只要执行一次构造函数。

Q 40 :

题目:
    如下程序段:
    char a[] = "xyz", b[] = {'x', 'y', 'z'};
    if(strlen(a) > strlen(b))
        printf("a > b\n");
    else
        printf("a <= b\n");
    则程序输出:

答案:
    a<=b

解答:
    考察对strlen实现的理解。
    1. strlen函数判断字符串长仅仅是通过字符串末的'\0'(字符0)来确定。
    2. 数组b为标识具体'\0'位置,所以使用strlen结果至少大于等于3。

Q 41 :

题目:
    执行以下语句,输出结果为:
    char *p1 = "hello";
    char *p2 = "world";
    char *p3 = "a piece of cake";
    char *str[] = {p1, p2, p3};
    printf("%c", *(str[0] + 1));

答案:
    e

解答:
    考察指针、指针函数及其操作。
    1. str是指针数组,每个元素都是指针。str[0]代表的是
    char *类型指针p1。
    2. p1是char *类型,只想字符串"hello",所以这里“+1”代表
    以字符为单位,结果为'e'。

[Q 42]

题目:
    以下表达式那些会被编译器禁止:
    int a = 248, b = 4;
    int const c = 21;
    const int *d = &a;
    int *const e = &b;
    int const * const f = &a;

答案:
    *c = 32
    *d = 43
    e = &a
    f = 0x321f

解答:
    考察指针常量、常量指针。
    1. 区分是指针的值不会变还是指针指向的变量值不会变。
    2. 方法:
        如果 const 位于 * 的左侧,则 const 就是用来修饰指
        针所指向的变量,即指针指向为常量。
        如果 const 位于 * 的右侧, const 就是修饰指针本身,
        即指针本身是常量。
    3. 方法使用:
        int const c -> 变量c的值不可改变。
        const int *d -> const在*左(离指针远),修饰指向
        的变量 -> 指针d指向的变量不可变。
        int *const e-> const在*右(例指针近),修饰指针 
        -> 指针e的值不可变。
        int const * const f -> 有左有右 -> 值和指针均不可变。

Q 43 :

题目:
    以下描述正确的是:

答案:
    虚函数不能是内联函数
    父类的析构函数是非虚的,但是子类的析构函数是虚的,delete
    子类对象指针会调用父类的析构函数

解答:
    1. 虚函数不能是内联函数(编译时展开,必须有实体),不能是
    静态函数(属于自身类,不属于对象,而虚函数要求有实体),不
    能是构造函数(尚未建立虚函数表)。
    2. delete子类对象是一定会调用父类的析构函数的先调用子类的
    析构函数然后调用父类的析构函数。

Q 44 :

题目:
    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;
    }

答案:
    Base Init
    Base func

解答:
    考察虚函数。
    1. 类Derived继承自Base,先调用基类构造函数Base(),再调
    用基类的init(),输出Base Init。
        构造子类对象,基类中不会调用子类的虚函数:
            基类构造函数 -> 子类构造函数
            子类还没有构造,还没有初始化,属于未初始化对象
            基类不会去调用子类虚函数(哪怕子类中确实声明为虚函数)
    2. 虽然 ((Base *)&d)->func()是虚函数调用的样子,但
    func()跟本没有被定义为虚函数,基类指针访问基类的func()。

Q 45 :

题目:
    采用多路复用I/O监听3个套接字的数据时,如果套接字描述符分别
    是:5,17,19,则:
    select(int maxfd, struct fd_set* rdset, NULL, NULL)
    中的maxfd应取为:

答案:
    20

解答:
     1. maxfd是三个套接字描述符中最大数字加上1。

猜你喜欢

转载自blog.csdn.net/weixin_38337616/article/details/88761863