• 笔试强训48天——day13


    一. 单选

    1.下面叙述不正确的是()

    A 派生类一般都用公有派生
    B 对基类成员的访问必须是无二义性的
    C 赋值兼容规则也适用于多重继承的组合
    D 父类的公有成员在派生类中仍然是公有的
    正确答案:D

    赋值兼容规则:
    1.子类对象可以直接赋值给父类对象
    2.子类对象的地址可以直接赋值给父类对象
    3.子类的对象可以对父类对象的引用初始化

    class Base
    {};
    
    class D : public Base
    {};
    
    void main()
    {
        Base b;
        D d;
        
        //1
        b = d;
        
        //2
        Base *pb = &d;
        
        //3
        Base &rb = d;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

     

    2.下面 C++ 程序的运行结果是()

    #include 
    using namespace std;
    class parent {
    int i;
    protected:
    int x;
    public:
    parent() 
    { x = 0; i = 0; }
    void change()
     { x++; i++; }
    void display();
    };
    class son :public parent {
    public:
    void modify();
    };
    void parent::display() {
    cout << "x=" << x << endl;
    }
     v
    oid son::modify() {
    x++;
    } 
    i
    nt main() {
    son A;
    parent B;
    
    A.display();
    A.change();
    A.modify();
    A.display();
    
    B.change();
    B.display();
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    A x=1
    x=0
    x=2

    B x=2
    x=0
    x=1

    C x=0
    x=2
    x=1

    D x=0
    x=1
    x=2

    确答案:C

    A,B是两个不同的对象,有自己不同的空间地址
    自己改变自己的

     

    3. 关于虚函数的描述正确的是()

    A 派生类的虚函数与基类的虚函数具有不同的参数个数和类型
    B 内联函数不能是虚函数
    C 派生类必须重新定义基类的虚函数
    D 虚函数可以是一个static型的函数

    正确答案:B

    虚函数重写:三同!
    inline是关键字只是一种建议,内联函数要被展开,没有地址。虚表是需要地址的。
    可以不构成多态就不用重新定义

     

    4. 当一个类对象的生命周期结束后,关于调用析构函数的描述正确的是()

    A 如果派生类没有定义析构函数,则只调用基类的析构函数
    B 如果基类没有定义析构函数,则只调用派生类的析构函数
    C 先调用派生类的析构函数,后调用基类的析构函数
    D 先调用基类的析构函数,后调用派生类的析构函数

    正确答案:C

    有默认的析构函数,有没有定义都得调
    先调用父类的构造函数,再调用子类的构造函数
    先调用子类的析构函数,再调用父类的析构函数

     

    5. 以下关于纯虚函数的说法,正确的是()

    A 声明纯虚函数的类不能实例化
    B 声明纯虚函数的类成虚基类
    C 子类必须实现基类的
    D 纯虚函数必须是空函数

    正确答案:A

    虚基类是避免菱形继承双份的方法,与纯虚函数没有关系

     

    6.下列描述,正确的一共有多少个()

    1)const char *p,这是一个常量指针,p的值不可修改
    2)在64位机上,char *p= “abcdefghijk”; sizeof§大小为12
    3)inline会检查函数参数,所以调用开销显著大于宏
    4)重载是编译时确定的,虚函数是运行时绑定的
    A 1
    B 2
    C 3
    D 4

    正确答案:A

    常量指针:所指框架的值是一个常量,不能改变指针的指向
    指针常量:不能改变指针的指向,但是可以指针解引用改变所指空间的值
    区分:const在的左边是常量指针 const在的右边是指针常量
    这里是指针常量
    指针的大小就是8个字节,64位
    宏和内联都会被展开,运行时的效率没有太大区别

     

    7. C++将父类的析构函数定义为虚函数,下列正确的是哪个()

    A 释放父类指针时能正确释放子类对象
    B 释放子类指针时能正确释放父类对象
    C 这样做是错误的
    D 以上全错

    正确答案:A

    子类里面已经完整的包含了一个父类
    析构的时候只看类型——这里就只会调用父类析构函数
    会造成资源的泄漏
    定义成虚函数之后,形成一种多态,释放的时候就会自动去调用子类的析构函数

    void main()
    {
        Base *pb = new D;
        delete pb;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

     

    8. 下列关于多态性说法不正确的是( )

    A 多态性是指同名函数对应多种不同的实现
    B 重载方式仅有函数重载
    C 重载方式包含函数重载和运算符重载
    D 多态性表现为静态和动态两种方式
    正确答案:B

    还有运算符重载
    静态——重载
    动态——运行时决议

     

    9.分析一下这段程序的输出

    #include
    using namespace std;
    class B
    {
    
    public:
    B()
    {
    cout << "default constructor" << " ";
    }
     ~
    B()
    {
    cout << "destructed" << " ";
    } 
    B
    (int i): data(i)
    {
    cout << "constructed by parameter" << data << " ";
    }
    p
    rivate: int data;
    };
    B Play( B b)
    {
    return b;
    } 
    i
    nt main(int argc, char *argv[])
    {
    B temp = Play(5);//先构造出一个B(5)——调动一次构造方法 拷贝构造
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    A constructed by parameter5 destructed destructed
    B constructed by parameter5 destructed
    C default constructor" constructed by parameter5 destructed
    D default constructor" constructed by parameter5 destructed destructed
    正确答案:A

    调动一次有参的构造方法和两次次析构方法
    会产生一个临时的对象,拷贝构造给B
    但会存在编译器的优化

     

    10. 求输出结果

    #include 
    using namespace std;
    class A
    { 
    p
    ublic:
    virtual void print()
    {
    cout << "A::print()" << "\n";
    }
    };
    
     class B: public A
    { p
    ublic: virtual void print()
    {
    cout << "B::print()" << "\n";
    }
    };
    class C: public A
    { p
    ublic: virtual void print()
    {
    cout << "C::print()" << "\n";
    }
    };
    void print(A a)
    {
    a.print();
    }
     i
    nt main()
    {
        A a, *aa, *ab, *ac;
    B b;
    C c;
    aa = &a;
    ab = &b;
    ac = &c;
    
    a.print();
    b.print();
    c.print();
    
    aa->print();
    ab->print();
    ac->print();
    
    print(a);
    print(b);
    print(c);
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    A C::print() B::print() A::print() A::print() B::print() C::print() A::print() A::print() A::print()
    B A::print() B::print() C::print() A::print() B::print() C::print() A::print() A::print() A::print()
    C A::print() B::print() C::print() A::print() B::print() C::print() B::print() B::print() B::print()
    D C::print() B::print() A::print() A::print() B::print() C::print() C::print() C::print() C::print()
    正确答案:B

    通过对象访问——静态绑定
    父类指针访问——多态
    通过父类对象去访问,无论是哪一个子类对象,调用的都是父类的方法——不是多态

     

     

    二. 编程

    1. 参数解析

    链接

    在命令行输入如下命令:
    xcopy /s c:\ d:\e,
    各个参数如下:
    参数1:命令字xcopy
    参数2:字符串/s
    参数3:字符串c:\
    参数4: 字符串d:\e
    请编写一个参数解析程序,实现将命令行各个参数解析出来。

    解析规则:
    1.参数分隔符为空格
    2.对于用""包含起来的参数,如果中间有空格,不能解析为多个参数。比如在命令行输入xcopy /s
    “C:\program files” "d:“时,参数仍然是4个,第3个参数应该是字符串C:\program files,而不是
    C:\program,注意输出参数时,需要将”"去掉,引号不存在嵌套情况。
    3.参数不定长
    4.输入由用例保证,不会出现不符合要求的输入

    输入描述:
    输入一行字符串,可以有空格
    输出描述:
    输出参数个数,分解后的参数,每个参数都独占一行

    示例1:
    输入
    xcopy /s c:\ d:\e
    输出
    4 x
    copy
    /s
    c:\
    d:\e

    正确答案:

    #include 
    #include 
    #include 
    using namespace std;
    
    void cmdLine(const string &str)
    {
        string tmp = "";
        int flag = false;//标记是否是字符串
        vector<string> cur;//cur是一个以string为单位的向量
        for(int i = 0;i<str.size();i++)
        {
            if(str[i] == '"')
            {
                flag = !flag;//变成true就是证明是字符串里的,空格就不作为分隔符
            }
            else if(str[i] == ' ' && !flag)//不是字符串里的空格,才是分隔符
            {
                cur.push_back(tmp);//遇到空格就将之前保存在tmp的内容尾插到cur中
                tmp = "";//置空,再次以空字符串进行下一个判断
            }
            else//没有遇到空格就加等到另外一个字符串中
            {
                tmp += str[i];
            }
        }
    
        cur.push_back(tmp);//将最后一个字符串尾插到cur中,因为最后一个后没有空格
        cout<<cur.size()<<endl;
        for(int i = 0;i<cur.size();i++)
        {
            cout<<cur[i]<<endl;
        }
    }
    
    int main() {
        
        string str;
        while(getline(cin,str))
        {
            cmdLine(str);
    
        }
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

     

    2. 跳石板

    链接

    小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3…
    这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个
    约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想
    跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。

    例如:
    N = 4,M = 24:
    4->6->8->12->18->24
    于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板

    输入描述:
    输入为一行,有两个整数N,M,以空格隔开。 (4 ≤ N ≤ 100000) (N ≤ M ≤ 100000)
    输出描述:
    输出小易最少需要跳跃的步数,如果不能到达输出-1

    示例1:
    输入
    4 24
    输出
    5

    正确答案:

    #include 
    #include 
    #include 
    #include
    using namespace std;
    
    void get_div(int v,vector<int> &a)
    {
        for(int i = 2;i<=sqrt(v);i++)//开方要包头文件
        {
            if(v%i == 0)
            {
                a.push_back(i);
                //将开方的一半传过去
                if(v/i != i)
                a.push_back(v/i);
            }
        }
    }
    
    int Jump(int n,int m)
    {
        vector<int> step(m+1,INT_MAX);//INT_MAX表示不可以达到,要包含头文件,m+1多开一个空间的位置
        step[n] = 0;//初始化其实位置,一开始站的位置是n,表示第0步
    
    //从n开始跳到m的位置
        for(int i = n;i<m;i++)
        {
            //如果n是不可到达的位置就结束
            if(step[i] == INT_MAX)
            continue;
    
            vector<int> a;
            get_div(i,a);//获取i的约数,并保存到a中
    
    
    //计算步数
            for(int j = 0; j<a.size();j++)
            {
                if(a[j]+i<=m && step[a[j]+i] != INT_MAX)
                {
                    //需要挑选一个最小值
                    step[a[j]+i] = step[a[j]+i] < step[i]+1 ? step[a[j]+i] : step[i]+1;
    
                }
                else if(a[j] + i <= m)
                {
                    step[a[j]+i] = step[i] + 1;
                }
            }
        }
        return step[m] == INT_MAX ? -1 : step[m];
    
    }
    
    int main() {
        int n,m,min_step;
        while(cin>>n>>m)
        {
            min_step = Jump(n,m);
            cout<<min_step<<endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
  • 相关阅读:
    Qt 设置软件的版本信息:QMake、CMake工程
    c++基础(十五)——多态
    【云原生专题】基于Docker+Neo4j图数据库搭建企业级分布式应用拓扑图
    【JAVA】会话跟踪技术
    栈的基本操作(数据结构)
    UDP协议
    15:00面试,15:06就出来了,问的问题有点变态。。。
    源码解析springbatch的job是如何运行的?
    Unity3D : 本地坐标系,世界坐标系,和TransformPoint,TransformVector,TransformDirection的区别
    前端必读:如何在 JavaScript 中使用SpreadJS导入和导出 Excel 文件
  • 原文地址:https://blog.csdn.net/Ll_R_lL/article/details/127587747