【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

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问