【C++笔试强训】第十六天

发布于:2022-10-29 ⋅ 阅读:(676) ⋅ 点赞:(0)

🎇C++笔试强训


  • 博客主页:一起去看日落吗
  • 分享博主的C++刷题日常,大家一起学习
  • 博主的能力有限,出现错误希望大家不吝赐教
  • 分享给大家一句我很喜欢的话:夜色难免微凉,前方必有曙光 🌞。

在这里插入图片描述

💦🔥


选择题

💦第一题

下列一段 C++ 代码的输出结果是()

#include <iostream>
class Base{
public:
int Bar(char x){
	return (int)(x);
}
virtual int Bar(int x){
	return (2 * x);
}
};
class Derived : public Base{
public:
int Bar(char x){
	return (int)(-x);
}
int Bar(int x){
	return (x / 2);
}
};
int main(void){
	Derived Obj;
	Base *pObj = &Obj;
	printf("%d,", pObj->Bar((char)(100)));
	printf("%d,", pObj->Bar(100));
}

A 100,-100
B 100,50
C 200,-100
D 200,50

首先实例化子类,然后用一个父类的指针接受子类的地址,第一个调动没有虚函数,调动父类,所以是100,第二个调用有虚函数,所以会调用子类,所以会重写,所以是50

这道题的答案是B


💦第二题

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

A 虚函数是一个static型的函数
B 派生类的虚函数与基类的虚函数具有不同的参数个数和类型
C 虚函数是一个非成员函数
D 基类中说明了虚函数后,派生类中起对应的函数可以不必说明为虚函数

A 静态函数没有this,虚函数调动虚幻this

B 如果父类和子类没有任何关系才会具有不同的参数个数和类型,这样问想问的是重写的时候,需要三同才可以重写,参数列表,返回值,函数名称都要相同

C 虚函数必须是是成员函数,是成员函数才能形成虚表,才能存放地址

D 对应子类的函数可以不必说明是虚函数

这道题的答案是D


💦第三题

代码执行后,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
B 5 10
C 100 200
D 100 10

需要考虑虚函数表,指向虚函数表的指针在32位系统下占用4个字节,其地址分布在整个类成员变量的地址的首部,接下来就是变量a的地址、b的地址。

当将test对象obj赋给指向整型的pInt后,指针pInt指向了地址的首部也就是虚函数表指针,所以*(pInt+0)=100改变的是虚函数表的值,接下来*(pInt+1)=200改变的是变量a的值,变量b没有变换。

这道题的答案是A


💦第四题

当一个类的某个函数被说明为virtual,则在该类的所有派生类中的同原型函数_____?

A 只有 被重新说明时才识虚函数
B 只有被重新说明为virtual时才是虚函数
C 都不是虚函数
D 都是虚函数

基类中说明了虚函数后,派生类中起对应的函数可以不必说明为虚函数,

请添加图片描述

这道题的答案是D


💦第五题

下面有关虚函数和非虚函数的区别说法错误的是?

A 子类的指针访问虚函数访问的是子类的方法
B 子类的指针访问非虚函数访问的是子类的方法
C 父类的指针访问虚函数访问的是父类的方法
D 父类的指针访问非虚函数访问的是父类的方法

子类的指针访问的是子类的方法,跟是不是虚没有关系

父类的指针访问虚函数访问的是子类的方法,因为被重写了,访问的是子类的方法

这道题的答案是C


💦第六题

下列程序的输出结果:

#include <iostream>
using namespace std;
class A
{
public:
	void print()
	{
		cout << "A:print()";
	}
};
class B: private A
{
public:
	void print()
	{
		cout << "B:print()";
	}
};
class C: public B
{
public:
	void print()
	{
		A:: print();
	}
};
int main()
{
	C b;
	b.print();
}

A A:print()
B B:print()
C 编译出错

B是私有继承A,子类不可以访问父类的私有成员,所以会编译出错,调不动

这道题的答案是C


💦第七题

以下关于C++的描述中哪一个是正确的()

A 任何指针都必须指向一个实例
B 子类指针不可以指向父类实例
C 任何引用都必须指向一个实例
D 引用所指向的实例不可能无效

B 子类指针不可以指向父类实例 向下转换本质上不可以,但是可以通过强转进行

引用即为一个变量的别名,所以必须实例化,而不能只有声明,而指针变量可以为null

D 创建后释放掉请添加图片描述

这道题的答案是C


💦第八题

下面关于多态性的描述,错误的是()

A C++语言的多态性分为编译时的多态性和运行时的多态性
B 编译时的多态性可通过函数重载实现
C 运行时的多态性可通过模板和虚函数实现
D 实现运行时多态性的机制称为动态绑定

C++语言的多态性分为编译时的多态性和运行时的多态性,编译时的多态性可通过函数重载实现,实现运行时多态性的机制称为动态绑定

C 运行时的多态性可通过模板和虚函数实现 ,模版和多态没有关系

这道题的答案是C


💦第九题

写出下面程序的输出结果

class A
{
public:
void FuncA()
{
printf( "FuncA called\n" );
}
virtual void FuncB()
{
printf( "FuncB called\n" );
}
};
class B : public A
{
public:
void FuncA()
{
	A::FuncA();
	printf( "FuncAB called\n" );
}
virtual void FuncB()
{
	printf( "FuncBB called\n" );
}
};
void main( void )
{
	B b;
	A *pa;
	pa = &b;
	A *pa2 = new A;
	pa->FuncA();3)
	pa->FuncB();4)
	pa2->FuncA();5)
	pa2->FuncB();
	delete pa2;
}

A FuncA called FuncB called FuncA called FuncB called
B FuncA called FuncBB called FuncA called FuncB called
C FuncA called FuncBB called FuncAB called FuncBB called
D FuncAB called FuncBB called FuncA called FuncB called

B b;
A *pa;
pa = &b;
A *pa2 = newA;
pa->FuncA(); ( 3)//pa=&b动态绑定但是FuncA不是虚函数,所以FuncA called
pa->FuncB(); ( 4)//FuncB是虚函数所以调用B中FuncB,FuncBB called
pa2->FuncA(); ( 5)//pa2是A类指针,不涉及虚函数,调用的都是A中函数,所以FuncA called FuncB called
pa2->FuncB()

这道题的答案是B


💦第十题

#include<iostream>
using namespace std;
class Base
{
public:
	virtual int foo(int x)
	{
		return x * 10;
	}
	int foo(char x[14])
	{
		return sizeof(x) + 10;
	}
};
class Derived: public Base
{
	int foo(int x)
	{
		return x * 20;
	}
	virtual int foo(char x[10])
	{
		return sizeof(x) + 20;
	}
} ;
int main()
{
	Derived stDerived;
	Base *pstBase = &stDerived;
	char x[10];
	printf("%d\n", pstBase->foo(100) + pstBase->foo(x));
	return 0;
}

在32位环境下,以上程序的输出结果是?

A 2000
B 2004
C 2014
D 2024

int foo(char x[14]) 参数传的是指针,指针是4个字节,所以这是这道题的关键点

这道题的答案是C


编程题

🔥 第一题

链接:完全数计算

请添加图片描述

  • 解题思路:

本题可以通过遍历每一个约数,求和,判断完全数。约数计算可以遍历sqrt(n)的范围。

  • 代码演示:
#include <iostream>
using namespace std;

int find_num(int n)
{
    int count = 0;
    int sum = 0;
    for(int i = 2;i <= n;i++)//效率不高
    {
        sum = 0;
        for(int j = 1;j < i; ++j)
        {
            if(i % j == 0)//对约数求和
                sum += j;
        }
        if(sum == i)
            count++;
    }
    return count;
}

int main()
{
    int n;
    int count;
    while(cin >> n)
    {
        count = find_num(n);
        cout << count << endl;
    }
    return 0;
}

🔥 第二题

链接:扑克牌大小

请添加图片描述

  • 题目解析

本题的题目意思是输入的只是这些类型中的一种,个子,对子,顺子(连续5张),三个,炸弹(四个)和对王。其实就是最多5张牌(顺子),最少1一张牌之间的比较。不存在其他情况。

  • 解题思路

由输入保证两手牌都是合法的,顺子已经从小到大排列,按照题意牌面类型的确定和大小的比较直接可以转换为牌个数的比较。

  • 代码演示:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

string FindMax(const string &brand)
{
    if(brand.find("joker JOKER") != string::npos)
        return "joker JOKER";
    
    int dash = brand.find('-');
    //分开两手牌
    string car1 = brand.substr(0,dash);
    string car2 = brand.substr(dash+1);

    //获取两首牌的张数,判断是否是相同类型
    int car1_cnt = count(car1.begin(),car1.end(),' ') + 1;
    int car2_cnt = count(car2.begin(),car2.end(),' ') + 1;

    //获取两手牌的各自第一张牌
    string car1_first = car1.substr(0,car1.find(' '));
    string car2_first = car2.substr(0,car2.find(' '));

    if(car1_cnt == car2_cnt) //两手牌的类型相同
    {
        string str = "345678910JQKA2jokerJOKER";
        if(str.find(car1_first) > str.find(car2_first))
            return car1;
        return car2;
    }

    if(car1_cnt == 4) //说明是炸弹
        return car1;
    else if(car2_cnt == 4) 
        return car2;
    
    return "ERROR";
}

int main()
{
    string brand,res;
    while(getline(cin,brand))
    {
        res = FindMax(brand);
        cout << res << endl;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到