【C/C++笔试练习】多态的概念、虚函数的概念、虚表地址、派生类的虚函数、虚函数的访问、指针引用、动态多态、完全数计算、扑克牌大小

本文主要是介绍【C/C++笔试练习】多态的概念、虚函数的概念、虚表地址、派生类的虚函数、虚函数的访问、指针引用、动态多态、完全数计算、扑克牌大小,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • C/C++笔试练习
  • 选择部分
    • (1)多态的概念
    • (2)虚函数的概念
    • (3)虚表地址
    • (4)派生类的虚函数
    • (5)虚函数的访问
    • (6)分析程序
    • (7)指针引用
    • (8)动态多态
    • (9)分析程序
    • (10)分析程序
  • 编程题 day16
    • 完全数计算
    • 扑克牌大小

C/C++笔试练习

选择部分

(1)多态的概念

  下列一段 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

  答案:B

int main(void)
{Derived Obj;//1.首先实例化一个子类对象Base* pObj = &Obj;//2.让父类指针接受子类的地址,形成多态printf("%d,", pObj->Bar((char)(100)));//3.调用Bar函数(参数是char),直接调用父类的Bar函数printf("%d,", pObj->Bar(100));//4.调用Bar函数(参数是int),形成多态,调用的是子类的Bar函数
}

在这里插入图片描述

  

(2)虚函数的概念

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

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

  答案:D

  A.虚函数不可以是static。因为static函数保存在静态区中,在静态区中的虚函数没有this指针,就无法找到自身的函数地址,以此来生成虚表。

  B. 派生类的虚函数和基类的虚函数应该有相同的参数个数和类型,这样才能保证多态性。 如果派生类的虚函数和基类的虚函数参数不同,那么在调用时会发生错误。

  C. 虚函数必须是类的成员函数,不能是非成员函数。同A一样,如果是非成员函数就没有this指针,也无法生成虚表,因此无法实现多态。

  D. 在C++中,如果基类中的函数被声明为虚函数,那么派生类中的相应函数默认也是虚函数,不需要显式声明。 这是C++的隐式虚函数。

  

(3)虚表地址

  代码执行后,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 bint* 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

  答案:A

int main()
{Test obj(5, 10);//1.直接创建Test类型的成员obj,将a=5,b=10int* pInt = (int*)&obj;//2.使用int类型指针,指向obj对象*(pInt + 0) = 100;//3.因为有虚函数的生成,所以此时改变的是虚表的地址,将虚表地址赋值为100*(pInt + 1) = 200;//4.此时将a的值赋值为200,b不变,cout << "a = " << obj.getA() << endl;//5.打印a,bcout << "b = " << obj.getB() << endl;return 0;
}

在这里插入图片描述

  

(4)派生类的虚函数

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

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

  答案:D

  当一个类的某个函数被说明为virtual时,该函数就成为该类的一个虚函数。在派生类中,如果与基类中的虚函数具有相同的函数原型(即参数个数、类型和顺序相同),则该函数也被视为虚函数,无论是否显式地声明为virtual。

  这是因为在派生类中,基类中的虚函数仍然是可访问的,并且可以通过虚函数表进行动态绑定。 因此,在该类的所有派生类中,同原型的函数都是虚函数。因此,答案为D。

  

(5)虚函数的访问

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

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

  答案:C

  父类的指针访问虚函数时(前提是构成多态的情况下),访问的是子类的方法,而不是父类的方法。这是因为虚函数使用了动态绑定机制,在运行时根据对象的实际类型来确定调用哪个函数。因此,如果父类的指针指向的是子类对象,那么访问虚函数时会调用子类的方法。

  其他选项的说法是正确的。子类的指针访问虚函数或非虚函数时,访问的都是子类的方法。父类的指针访问非虚函数时,访问的是父类的方法。 因此,答案为C。

  

(6)分析程序

  下列程序的输出结果:

#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. 编译出错

  答案:C

  class B: private AB私有继承A,无法访问A中的私有成员函数。

在这里插入图片描述

  

(7)指针引用

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

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

  答案:C

  A. 在C++中,指针可以被初始化为nullptr或者未初始化, 这两种情况下指针不指向任何实例。此外,指针也可以指向已经被销毁的对象,这种情况下指针同样不指向有效的实例。

  B. 在C++中,子类指针可以指向父类实例,这是因为子类继承了父类的所有成员和函数,所以子类指针可以访问父类的所有成员和函数。但是,如果通过子类指针访问父类实例中不存在的成员或函数,会导致编译错误或运行时错误。

  C. 在C++中,引用必须在声明时被初始化,且一旦初始化后就不能再改变引用的对象。 因此,引用必须指向一个有效的实例,否则会导致编译错误。

  D. 引用所指向的实例可能会变得无效,例如,如果引用所指向的对象被销毁或者引用被重新赋值指向其他对象,那么原来的引用就变得无效了。此外,如果引用所指向的对象是局部变量或临时对象,在对象生命周期结束后,引用也会变得无效。

  

(8)动态多态

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

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

  答案:C

  多态性是指用同一个函数名调用不同的对象,产生不同的结果。多态性分为两种:编译时多态性和运行时多态性。

  编译时多态性是通过函数重载(overloading)实现的。函数重载是指在同一作用域内可以定义多个同名的函数,它们具有不同的参数类型或参数个数。 编译器在编译阶段根据调用函数时使用的实参类型和数量,选择对应的函数版本进行调用。

  运行时多态性是通过虚函数(virtual functions)实现的。虚函数是基类中声明的函数,它可以在派生类中被重写。通过将基类的指针或引用指向派生类对象,并调用该指针或引用上的虚函数, 程序可以在运行时确定调用哪个类的函数版本。这种机制称为动态绑定(dynamic binding)。

  模板是一种编译时多态性,它允许我们使用一种类型不确定的方式编写代码,并在编译时根据实际类型生成对应的代码。

  A选项描述了C++中多态性的分类,是正确的。

  B选项指出编译时的多态性可以通过函数重载实现,也是正确的。

  C选项错误地声称运行时的多态性可以通过模板实现。实际上,模板是编译时多态性的特性。

  D选项描述了实现运行时多态性的机制,是正确的。

  

(9)分析程序

  写出下面程序的输出结果

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

void main(void)
{B b;A* pa;pa = &b;pa->FuncA();  //1.pa指针指向b对象,此时调用FuncA,不构成多态,打印Apa->FuncB();  //2.此时父类指针指向子类,"三同"形成多态,调用子类函数,打印BBA* pa2 = new A;pa2->FuncA();  //3.父类指针调用父类函数,打印Apa2->FuncB();  //4.同3,打印Bdelete pa2;
}

在这里插入图片描述

  

(10)分析程序

#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

  答案:C

int main()
{Derived stDerived;Base* pstBase = &stDerived;//1.多态形成char x[10];                //2.此时父类指针调用foo函数,因为多态,调用子类函数,100*20=200printf("%d\n", pstBase->foo(100) + pstBase->foo(x));//3.此时父类指针直接调用父类函数,8+10=18,一共是2000+18=2018return 0;                                           //注意32位下指针是4字节,64位下指针是8字节
}

在这里插入图片描述

            

编程题 day16

完全数计算

完全数计算

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

#include<iostream>
using namespace std;int Count_Of_Perfect_Number(int n) 
{int count = 0, sum = 0;for (int i = 2; i <= n; ++i) {for (int j = 1; j < i; ++j) { if (i % j == 0) //对约数进行求和sum += j;}if (sum == i)count++;sum = 0;}return count;
}int main() 
{int n, count;while (cin >> n) {count = Count_Of_Perfect_Number(n);cout << count << endl;}return 0;
}

  

扑克牌大小

扑克牌大小

  解题思路:本题的题目意思是输入的只是这些类型中的一种,个子,对子,顺子(连续5张),三个,炸弹(四个)和对王。其实就是最多5张牌(顺子),最少1一张牌之间的比较。不存在其他情况。由于输入保证两手牌都是合法的,顺子已经从小到大排列,按照题意牌面类型的确定和大小的比较直接可以转换为牌个数的比较。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;string FindMax(const string& line) 
{if (line.find("joker JOKER") != string::npos)return "joker JOKER";int dash = line.find('-');//分开两手牌string car1 = line.substr(0, dash);string car2 = line.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 line, res;while (getline(cin, line)) {res = FindMax(line);cout << res << endl;}return 0;
}

这篇关于【C/C++笔试练习】多态的概念、虚函数的概念、虚表地址、派生类的虚函数、虚函数的访问、指针引用、动态多态、完全数计算、扑克牌大小的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/475804

相关文章

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例:

C#中图片如何自适应pictureBox大小

《C#中图片如何自适应pictureBox大小》文章描述了如何在C#中实现图片自适应pictureBox大小,并展示修改前后的效果,修改步骤包括两步,作者分享了个人经验,希望对大家有所帮助... 目录C#图片自适应pictureBox大小编程修改步骤总结C#图片自适应pictureBox大小上图中“z轴

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

使用Python实现批量访问URL并解析XML响应功能

《使用Python实现批量访问URL并解析XML响应功能》在现代Web开发和数据抓取中,批量访问URL并解析响应内容是一个常见的需求,本文将详细介绍如何使用Python实现批量访问URL并解析XML响... 目录引言1. 背景与需求2. 工具方法实现2.1 单URL访问与解析代码实现代码说明2.2 示例调用

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规