C++ | 深入浅出类的封装思想【图文案例,通俗易懂】-3

简介: C++ | 深入浅出类的封装思想【图文案例,通俗易懂】

4、两道夺命面试题👻

本小节的内容可能会让你感到非常枯燥,如果没有校招需求的读者可以选择跳过,当然也可以浏览一下喽😆

this指针存放在哪里?

先来看看第一位同学的回答:

💬 this指针是存放对象地址的,和对象存在关系。应该是存放在对象中的把😁

  • 听完了他这一番话,我差点没拿起我的四十米大刀🔪抡过去(╯▔皿▔)╯,刚才我们讲到了有关this指针的特性,现在再重复一遍。它是作为成员函数的隐含形参,既然是函数形参的话,那就需要压栈、建立栈帧,所以这个this指针是存放在栈上的。
  • 不过在VS中,编译器会使用寄存器ecx进行一个临时保存,刚才我们也有通过汇编指令进行一个查看

image.png

再来听听第二位同学的回答:

💬 刚才不是说这个成员函数是存放在公共代码区的吗,那隐藏形参this是属于这个函数的,为何没有存放在公共代码区呢?

  • 这个问题其实问得不错,不过这属于一个知识混淆了,不要把【栈区】和【公共代码区】混为一谈
  • 我们现在对一段程序进行编译,实例化出一个对象后这个对象就是存在【栈区】中的,但是成员函数不存放在其中,因为成员函数是属于公共区域的一部分,所以在编译完成之后,call指令的地址不在对象中找,而去【公共代码区】中找,为什么要去这个公共区找呢?因为成员函数被编译出来的这些指令(刚才看的指令)存放在这里面, 而成员函数内部的一些形参、临时变量则不在这里面,它们都是存放在【栈区】中的。所以this指针不在【公共代码区】,而在【栈区】
  • 听完我的这番话后,这个同学似乎就明白了一些东西

this指针可以为空吗?

好,接下去我们再来看第二个面试题

💬请问下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

class Date {
public:
  //定义
  //void Init(Date* this, int year, int month, int day)
  void Init(int year, int month, int day)
  {
    cout << "this:" << this << endl;
    this->_year = year;
    this->_month = month;
    this->_day = day;
  }
  void Print()
  {
    cout << "Print()" << endl;
  }
private:
  int _year;  //仅仅是声明,并没有开出实际的空间
  int _month;
  int _day;
};
int main()
{
  Date* p = nullptr;
  p->Print();
}

运行结果:

image.png

  • 看了上面的运行结果,你是否感觉很吃惊😮,为何没有【运行崩溃】呢?为什么可以对一个空指针去解引用呢?
  • 可以知道这个Print()是Date类的一个成员函数,那既然是成员函数的话就可以调用this指针,我们来试试

image.png

  • 可以看到this指针所接收到的地址为空,这很明确,我们在因为在外界调用这个函数的对象指针就是空的。那可以看出其实从调用到函数内部的执行完全没有进行一次解引用的操作,所以才不会引发空指针异常的问题

  • 不过呢,就上面的这一个还考察不出一个人对this指针的理解,一般考了上面这个还会接连着考下面这个
p->Init(2023, 3, 19);

运行结果:

image.png

  • 很明显,若是去调用Init()初始化函数的话就会发生空指针异常的问题,这是为什么呢?

💬有同学说:一看就是这个this->的问题,很明显的解引用嘛,去掉不就好了😎

  • 然后继续给他看了这个,他便陷入了沉思🤨

image.png

  • 这里要说明一点,本模块一开始我们初谈this指针的时候说到, 在成员函数内部调用成员变量时,可以在前面加上this->去指向,当然也可以不加,因为是默认带有的,所以在这里无论是显式地加上还是隐式让他保留,都会产生一个【指针指向】,那我们在C语言的指针章节有谈到,==对于指针指向而言其实就是解引用==,所以这才造成了出错

通过上面这两个函数的调用,相信你对this指针传参机制有了一些基本认识。但还是没有清楚这其中的原理,接下来我便带你分析一下里面的原理

  • 上面有说到过,对于成员函数而言是不存在于类内部的,而是存放于【公共代码区】,所以对于上面的这两个函数而言都不去类里找,即【栈区】里找,而是通过函数名修饰后的名称去【公共代码区】里找
  • 对于Print()函数而言,并没有涉及到访问成员变量,那你可以把它理解为在别人家的小区里的公共蓝球场🏀打了个篮球,那这其实是属于公共的区域,而没有闯入别人的私人领地
  • 使用空指针去调用了一下这个函数,此时传递这个空对象的地址给到成员函数内部的【this】指针,然后我去打印了一下这个this指针,那也就是将这个对象的地址给打印出来,因为它是一个空对象,所以结果是00000000。但是并没有再做任何的事了,所以不会有问题
  • 就比方说你手里有一把刚从刀柄里拔出来的刀🔪,但也只是从刀柄里拔出来看看,并没有那它去做任何坏事,伤害到别人,那也没什么问题嘛╮(╯▽╰)╭

  • 当在调用这个Init()函数时,也不是去【栈区】里找,而是去【公共代码区】里找,也是一样首先打印了一下传入的空对象地址,不过接下来的操作就不对了!只要是要访问当前类的成员变量时,都需要使用到this指针来进行指向,只是因为它是一个隐式形参罢了
  • 打个比方,你又进到别人家小区了,但是呢此时却没有经过别人的同意随意地躺在别人家沙发上:bed:上,这个沙发就属于别人的私有物品,也可以看做是成员变量,刚才我们并没有访问成员变量,所以是没问题的,但是现在却访问了一个私有的东西,那报出错误也是很正常的

💬那有同学又说:那我在调用Init()的时候不传空对象不就好了,直接调用

Init(2023, 3, 19);
  • 你觉得这样可以吗?==我让他罚站了半个小时~==
  • 上面我们说到,若是一个定义出来的对象去调用成员函数,会有一个隐藏的形参this接受传递过来的对象地址,以此去调用不同对象的成员变量。但是就上面这个调用,连执行的对象都没有,你觉得this指针会接收到什么东西呢?
  • 通过运行结果可以看出,连编译都过不了,谈何运行呢?

image.png

好,看完了上面这一些,相信你对this指针的了解一定更加深刻了,我们再来看最后一个👇

💬还是调用刚才的Print()函数 A、编译报错 B、运行崩溃 C、正常运行

(*ptr).Print();
  • 在学习了上面的两道题后,相信你一定会觉得这是个【编译报错】或者是【运行奔溃】,不过结果却大相径庭。竟然完全没有问题,可以正常运行!😮

image.png这是什么呢???

image.png

  • 若是你完全不懂这一点的话,应该再回过去看看指针的解引用那块,难道一个指针去进行指向->或者是解引用*就一定是在对指针进行解引用嘛
  • 不,会不会解引用取决于要不要到指向的对象中去找成员变量,而不是看有没有”->“。因为对于编译器来说,是将代码的这些语法转换为指令,我们要去看的是这些汇编指令

image.pngimage.png

  • 通过上面的观察可以看出,从【汇编角度】而言,其实编译器把->*解析成了同一种方式,至于内部的逻辑是怎么样的,上面已经讲过了,此处不再赘述

💬最后,有位同学又提出了这样的写法,蛮不错的,给读者分享一下

  • 你认为下面这种直接用类名然后【域作用限定符::】的方式去访问可行吗?
Date::Print();

运行结果如下:

image.png

  • 对于这种调用形式,我们在上面其实也提到过,只有静态的成员函数或者是静态的成员变量才可以用类名直接访问,所以这样是不可以的,也是一种没有传入当前对象地址给this指针的形式

💬为什么没有让她罚站呢,怎么能让女生👩罚站呢,是吧😆

5、一道笔试题✍

💬下面程序段包含4个函数,其中具有隐含this指针的是( )

int f1();
class T
{
public:static int f2();
private:friend int f3();
protect:int f4();
};

【答案】:f4

【解析】:

  1. f1为全局函数,不是类的成员函数,因此没有this指针
  2. f2为static函数,放在公共代码段,不属于类,因此没有this指针
  3. f3为友元函数,不属于类,因此没有this指针
  4. f4为成员函数,在类T中具有保护权限,因此有this指针

好,接下去就对上面的笔试和面试题所引申出来的知识点做一个总结与回顾,我们就进入下一模块

【总结一下】:

  • 对于this指针而言,是存放在【栈区】的,虽然其是属于成员函数的一个隐式形参,但是却不和成员函数一样存放在【公共代码区】,对于成员函数而言只是编译器将其解析后的汇编指令存放在公共区罢了,而对于函数内部的形参和临时变量,都还是存放在栈区的,是需要开辟栈帧、压栈的↓
  • this指针可以为空,但能不能正常运行取决于你如何去调用,仅仅是传递了空对象地址但没有进行解引用的话不会出现问题。但若是在成员函数内部访问成员变量的话,无论你有无给出this->,都会造成解引用从而导致空指针异常⚠的问题。
  • 看一个指针是否产生了介意用不是光光看->或者*,而是要去观察底层的汇编指令如何执行,这才是计算机内部的真正执行逻辑

八、C和C++实现栈的对比

好,讲了这么多,相信读者对C++的类这一块一定有了自己的理解,本模块,我将通过C语言和C++分别去实现一个【栈】,通过观察来让读者看出==C++到底是如何实现封装的==

1、代码展示

C语言的相关代码可以看这篇文章 链接,这里就不贴代码了

主要来展示一下C++的代码,下面是比较规范的声明与定义分离的形式,可以先看看

==stack.h==

typedef int DataType;
class Stack
{
public:
  void Init(size_t capacity = 4);
  void Check_Capacity();
  void Push(const DataType& data);
  void Pop();
  bool Empty();
  DataType Top();
  void Destroy();
private:
  DataType* _array;
  size_t _capacity;
  size_t _top;
};

==stack.cpp==

#include "stack.h"
void Stack::Init(size_t capacity)
{
  _array = (DataType*)malloc(sizeof(DataType) * capacity);
  if (nullptr == _array)
  {
    perror("malloc申请空间失败");
    return;
  }
  _capacity = capacity;
  _top = 0;
}
void Stack::Check_Capacity()
{
  if (_top == _capacity)
  { 
    DataType* tmp = (DataType*)realloc(_array, sizeof(DataType) * _capacity * 2);
    if (nullptr == tmp)
    {
      perror("fail realloc");
      exit(-1);
    }
    _array = tmp;
    _capacity = _capacity * 2;
  }
}
void Stack::Push(const DataType& data)
{
  // 扩容
  Check_Capacity();
  _array[_top] = data;
  ++_top;
}
bool Stack::Empty()
{
  return _top == 0;
}
void Stack::Pop()
{
  assert(_top > 0);
  assert(!Empty());
  _top--;
}
DataType Stack::Top()
{
  return _array[_top - 1];
}
void Stack::Destroy()
{
  if (_array)
  {
    free(_array);
    _array = nullptr;
    _capacity = 0;
    _top = 0;
  }
}

==test.cpp==

int main(void)
{
  Stack st;
  st.Init();
  st.Push(1);
  st.Push(2);
  st.Push(3);
  size_t top = st.Top();
  cout << top << endl;
  st.Pop();
  top = st.Top();
  cout << top << endl;
  st.Destroy();
  return 0;
}

运行结果:

image.png


  • 其实除了C/C++之外,像其他语言例如Java都是可以实现一个栈的【链接】,只不过语言的立场、语法的细节不一样而已
  • 如果平常自己懒得去写,直接使用库里面给我们写好的就行,C++和Java都有现成的库给我们封装好了,只需要调用一下需要的API即可,像我们后续会学习的STL中stack,里面就有上面所学的全部内容

2、C语言特性分析

  1. 数据和方法是分离的
  • 这一点其实很好观察,当我们使用C语言去写一个栈的时候,是将存放数据的数组、栈顶指针、容量大小都放在结构体中,其他算法接口再另外分离写,二者的关联性并不是很大

image.png

  1. 数据访问控制是自由的,不受限制
  • 还有第二点,就是在C语言中,我们去访问一个数据的时候,其实是比较自由的,不会受到过多的限制。
  • 举个例子,当初我们在数据结构中写栈的StackTop()时,产生了分歧,有的同学说直接像下面这样取就可以了
int top1 = st->a[st->top - 1];   
  • 但是呢有的同学却觉得即使是再小的功能也应该封装成为一个函数的形式,之后再去进行调用
int top2 = StackTop(&st);
  • 我赞同了上面这种写法,还记得为什么吗?因为对于外界来说是无法知晓你底层的逻辑实现是怎样的,若是写成第一种形式的话,调用者就得知道当前这个栈在初始化的时候top指针初始化的值是多少,是-1呢?还是0呢?
  • 但若是采用第二种写法,调用者完全不需要关心这个函数内部的实现细节,只需要进行调用即可,就会显得很方便
asssert(top > 0);
  • 不仅如此,若是采取第一种形式的话,访问者不仅要知道底层top指针初始化为多少,而且还要知道当前栈中还有多少数据了,因为我们在去栈顶元素前都会去使用一个assert()进行检查,此时若是这个栈顶指针 <= 0的话也就表明栈里面没有元素了,再去通过数组访问的话就会造成有越界的风险

【总结一下】;

  • 使用C语言去进行访问的时候过于自由,因此需要考虑到很多因素
  1. 需要知道底层的top的初始化
  2. 有越界的风险,不安全

C语言语法的松散性 - - 过红绿灯还是慢一点吧🚦

虽说使用C语言这样去进行访问确实存在一些缺陷,那为什么标准委员会没有改进这一点呢?还是允许这样的访问。

  • 这其实就是因为C语言本身【语法的松散性】导致的,因为C语言的语法限制不太严格,对变量的类型约束不严格,影响程序的安全性,对数组下标越界不作检查等。所以C语言其实较其他高级语言来说其实更难掌握,==要求使用者对代码具备一定的的控制能力==
  • 那面对C语言中的一些缺陷,官方文档中的也只是建议说使用的时候不要这样去做,像上面那样直接访问栈顶元素的方式【不做推荐

但是推荐这个东西管用吗?

  • 举一个很形象的例子,日常我们在开车🚗经过十字路口的时候,都会有很多红绿灯来阻拦我们,此时就无法做到一路畅通,但是所谓的”红灯停,绿灯行,黄灯等一等”真的起到了什么作用吗?
  • 还是会存在大批行人闯红灯的现象,总有人不遵纪守法,导致出事故

image.pngimage.png

  • 要知道,这个世界永远存在不确定的事,不可能所有的事情都愿你想得那么美好,就好比我们日常在做开发的时候,总是需要考虑到各种各样的问题,为什么?因为用户的行为是不确定的,可能哪一天就会做出你在开发是会后根本想不到的事,因为我们写代码时需要考虑到各方面的因素

所以可以看出来C语言存在一定的不严谨性,而且C语言还比较乱,尤其体现在学校的教科书和一些相关书籍中

  • C++引用一文的,我有提到了很多学校的数据结构教材中的一些代码,其实是C和C++混编的,可以却告诉读者使用的是C语言是实现,就是因为C和C++之间有着一些联系,所以很多读者就会分不清哪个是C,那么是C++的代码
  • 不仅如此,在一些经典书籍中,也会出现类似的情况,这里点名说一本书叫做《大话数据结构》。如果你有看过这本书的话会觉得它里面的一些讲解和图其实都蛮好的,也挺适合初学者,不过呢里面的一些代码让人看起来确实有点难受🤢
  • 但凡你有去工作过的话,真的是看不上这本书的代码,可以说这个作者应该是缺乏一些工程经验,代码没有规范性

image.png

上面的一些种种案例其实都可以说明C语言在语法设计这一块确实是有些松散了,导致缺乏经验的初学者会遇到很多难题

3、C++的特性优势分析

再谈类的封装思想  - - 兵马俑还是保护起来吧🛡

  • 上面谈到了由于C语言在语法设计这一块存在松散性,因而导致了在使用的时候会有一些随机性和不确定性,存在一定的风险。但是C++在这一块却做得很好,一起来看看C++在封装这一块的思想
  1. 数据和方法都封装到类里面
  • C++做得很好是因为它并不是像C语言那样变量和函数都分离开来,而是将它们都封装到一个类里,全部保护起来了,外界是无法随意访问的
  • 初步谈到类的封装思想的时,说到【封装】其实就是一种更好地控制,更好地进行管理,现在我通过一个形象一点的案例再来描述一下这个封装的思想

image.png- 有去过西安的读者应该了解,这个六朝古都拥有世界八大奇迹之一的【秦始皇陵兵马俑】,是中华文化的瑰宝。从上图中我们可以看出,馆内将兵马俑都封在了中间的坑里,而外层则是一群群的游客,它们只能在站台上观看,而不可以下到坑洞里去触碰兵马俑 - 这其实指得就是一种【封装】的思想,将兵马俑全部保护起来,外人无法轻易接触到。若是不将这些兵马俑保护起来,谁都可以接触到,那么要不了一个月,兵马俑上到处都会刻着“xxx到此一游”“xxx爱xxx”,或者缺胳膊少腿image.png

  1. 控制访问方式。【愿意给你访问的共有,不愿意给你访问的私有】
  • 第二点呢就是在类的封装基础上,限定了外界的【控制访问方式】,若是想要给外界访问的就设置为共有public,不想给外界访问的就设置为私有private
  • 就比如说你去定义一个栈然后对其进行初始化,此时不能直接访问到这个类内部的成员变量,类会向外部提供一个公共的接口对私有的成员变量去进行一个访问
Stack st;
st.Init();
  • 这个共有的接口是类里面写好给你的,类写得没问题,那你用起来就不会有问题
  • 所以在C++中,我们要去获取栈顶元素的方式只有一种,那就是调用Top()成员函数,不需要去管内部的实现细节是怎样的,只需要调用就可以了
  • 而内部的数组和栈顶指针都设置为了私有,你是无法访问到的
int top = StackTop(&st);    //✔
int top = st->a[st->top - 1]; //❌

讲得通俗一点,还是用我们上面讲到过的红绿灯例子🚦

  • 行人老是闯红灯怎么办! 那就不让他过去了,把红绿灯给撤了,两遍围墙围起来不能通过马路,那怎么办呢?就弄一个高架桥,你想要过去只能走上面的高架桥,这也就一劳永逸杜绝了闯红灯的问题的,杜绝了安全隐患
  1. 调用函数比C语言要轻松一点,不用传入当前对象的地址
  • 如果你仔细观察C++和C语言实行去实现一个栈,不仅是类的封装这一块发生了大的改动,而且代码也简洁了不少,传入的参数均少了一个
//C语言实现
void PushStack(ST* st, STDataType x)
PushStack(&st, 1);
//C++实现
void Stack::Push(const DataType& data)
st.Push(1);
  • 那这么一对比确实有同学发现C++为何不用传当前对象的地址过去呢?
  • 那我想这位同学一定是忘了一个很重要的东西--> this指针。还记得this指针的原理吗 ?它是成员函数的一个隐藏形参,在当前对象调用成员函数时,当前对象的地址会连同其他参数一起压入栈中,VS中则是使用寄存器ecx来进行临时存放,最后再由成员函数中的this指针接受当前正在调用函数对象的地址,以此来访问不同对象的不同成员变量
  • 所以可以看出:对于C语言来说,是需要我们显式地传入当前对象的地址,是浮于水面的;对于C++来说,不需要我们去做这一件事,编译器自动会帮我们完成,是藏于水面下的

九、总结与提炼

到这里,就讲完了类的封装思想,我们来总结回顾一下:book:


  • 首先我们聊到了【面向过程】与【面向对象】之间的区别,初步感受了C语言和C++两门语言特性的不同。为了引出C++中的类,便对比了structclass这两个关键字,知道了原来在C++中结构体可以这么玩,并且二者都可以用在来定义一个
  • 接下去呢我们就正式开始聊C++中的类,说到了三种访问限定符,puiblcprotectedprivate,若是加上了访问限定符后,类内的成员对外部来说就存在不同的限制。初次讲到了类的封装思想,将对象的属性(数据)与操作数据的方法结合在一块,起到了更好地管理
  • 写好一个类后,就可以用它定义出一个对象了,在这一模块,通过形象地案例向读者展示了【声明】和【定义】之间的区别,如果要将一个东西定义出来,就要实实在在为其开出一块空间
  • 将类实例化后,就可以通过这个对象去调用类中的向外提供的共有成员函数来说来操控私有成员变量,但是在计算类的大小时却发现【成员函数】似乎并不计算在内,通过探究发现原来其存在于一个公共代码区,为什么减少类内部的负担,将大家都要使用的东西像小区中的公共设施一般放在一个【公共代码区】,这样谁要用的时候通过对应的地址找到然后去调用一下即可。==可是成员函数内部要如何知道是哪个对象来调用的我呢?==
  • 此时我们谈到了一个重要知识点 —— this指针随着每次的传入的对象地址不同,隐式形参this指针就会通过不同的地址去找到内存中对应的那块地址中的成员变量,进行精准赋值
  • 最后,在学习了C++中的类后,便去实现了我们之前在数据结构中写过的【栈】,对二者进行对比可以发现,原来C++在封装这一块的思想确实考虑得很周到,很好地解决了C语言因为语法松散而导致的各种不安全性,进一步加深了对【封装思想】的理解

以上就是本文要介绍的所有内容,Thanks for reading, see you next article:rose:

相关文章
|
10天前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
12天前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
10天前
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
10天前
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。
|
1月前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
72 19
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
57 13
|
1月前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
57 5
|
1月前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
47 5
|
1月前
|
Serverless 编译器 C++
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
本任务要求设计一个矩形类、圆形类和图形基类,计算并输出相应图形面积。相关知识点包括纯虚函数和抽象类的使用。 **目录:** - 任务描述 - 相关知识 - 纯虚函数 - 特点 - 使用场景 - 作用 - 注意事项 - 相关概念对比 - 抽象类的使用 - 定义与概念 - 使用场景 - 编程要求 - 测试说明 - 通关代码 - 测试结果 **任务概述:** 1. **图形基类(Shape)**:包含纯虚函数 `void PrintArea()`。 2. **矩形类(Rectangle)**:继承 Shape 类,重写 `Print
51 4
|
1月前
|
设计模式 IDE 编译器
【C++面向对象——类的多态性与虚函数】编写教学游戏:认识动物(头歌实践教学平台习题)【合集】
本项目旨在通过C++编程实现一个教学游戏,帮助小朋友认识动物。程序设计了一个动物园场景,包含Dog、Bird和Frog三种动物。每个动物都有move和shout行为,用于展示其特征。游戏随机挑选10个动物,前5个供学习,后5个用于测试。使用虚函数和多态实现不同动物的行为,确保代码灵活扩展。此外,通过typeid获取对象类型,并利用strstr辅助判断类型。相关头文件如&lt;string&gt;、&lt;cstdlib&gt;等确保程序正常运行。最终,根据小朋友的回答计算得分,提供互动学习体验。 - **任务描述**:编写教学游戏,随机挑选10个动物进行展示与测试。 - **类设计**:基类
41 3