笔试强训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;
}

 

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

#include <iostream>
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;
}

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;
}

 

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

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

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

 

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

#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 << " ";
}
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;
}

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 <iostream>
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);
} 

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 <iostream>
#include <string>
#include <vector>
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;
}

 

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 <iostream>
#include <vector>
#include <limits.h>
#include<math.h>
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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hey pear!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值