学习C++、QT---05(结构体和类)

发布于:2025-06-24 ⋅ 阅读:(12) ⋅ 点赞:(0)

每日一言

        今天的汗水,是浇灌明日成功的甘露。

数组

C++的数组和C语言的数组是一模一样的,所以不讲,而且到后面C++有更好用的数组,比如动态的数组等等

复习一下普通数组的写法:

比如int array[5]={1,2,3,4,5};

指针

C++完全兼容C语言指针,多出一个this指针,在面向对象中再讲解

结构体和类

我们利用C语言的结构体来引进类的讲解

这个是c语言的结构体

此结构体有两种书写方法,一种是数组,还有一种是指针,当然指针是最好的,因为不用去管边界,也就是不用考虑越界的问题,还有这边写了一个函数指针,结构体只能写函数指针去实现函数的功能,所以函数的实现体要在外部另起定义和实现就像这边的toyinfo和carinfo

因此有句话叫做:在 C 语言中,结构体不能直接包含函数,但可以包含函数指针通过函数指针间接实现 "结构体内部的函数"。

我们看到我们写的这个函数指针部分,这边需要讲解一下细节:

看到我们注释的这段还有下方这段 函数指针的写法,里面的参数部分,实际上是一样的,因为char address[20]是一个数组作为参数,那么数组作为参数就会隐式转换成数组的首地址,也就是指针,所以我们还不如直接写成指针的写法,这样更本质,

还有一个点你传进去数组比如char address[20]作为参数,实际上编译器不会看你的大小的,直接就是传的就是数组的第一个元素的地址进去

所以啊我们在看到这个toyinfo这边,为什么用%s这个是有原因的,因为%s的作用就是遍历完所有传进来的字符按照指针一个一个的,直到  \0 ,这样才对应的到我们的传值啊,因为我们也是传的char * address 是数组的首地址,才可以遍历下去啊,所以都是环环相扣的

要记住,我们因为结构体的写法是仅进行声明,不进行初始化

所以我们怎么进行对结构体中的数组进行“赋值”呢,那么就要我们定义一个结构体变量的时候进行用strcpy的形式,进行复制写入数据,记住哈,不能赋值,只能将数据进行复制,但是我们可以一直使用,知道下一次的复制

我们也无需释放:t和t.name在main()结束时自动销毁

我们的输出信息的方式我们也用了两种,一种是直接printf还有一种是我们使用函数指针来实现,切记我们需要在结构体外声明一个函数和函数指针参数形式一样的函数,这样我就可以用函数指针了,比如:将toyinfo()这个函数直接将函数名赋值给函数指针,这样就等于是讲函数toyinfo()的地址给了函数指针变量,那么cpu在执行代码的时候,到函数指针的地方的时候就会去找toyinfo函数,进而达到了; 我们想要结构体实现函数功能的作用

调用函数指针

babi.printinfo(babi.address, babi.name, babi.date);

等价于直接调用

toyinfo(babi.address, babi.name, babi.date);

所以给printinfo传的值,其实就是给toyinfo传的值

讲一下这边的,一定要讲清楚

首先呢这个struct car 这个结构体里面我们用的是指针变量,不是用的数组了,那么可以进行赋值了(用的是堆空间),所以这边我可以直接让BMW这个结构体变量的address =德国 然后我们就会去想,诶是不是空指针啊?那当然不是了,因为“德国”这个实际上是是字符数组,那么就会将第一个字符的地址传进去,也就是德的地址传给char * address,那么我们后面的%s就可以通过指针去遍历完所有的字符了

那么我们后面的定义的struct car *Audi 这是一个结构体指针变量,所以需要进行开辟内存空间,不然就是野指针啦,所以在c语言这边我们需要使用到malloc这个函数进行开辟内存空间,用的是堆空间,

然后我们的malloc因为原型是void类型的所以要转换成struct car *型,然后,开辟的空间用sizeof(struct car)这样就等于直接开辟了一个结构体的大小,永远也不会超,最优选择,习惯用法

然后后面的就是指针的用法了-> 指针用-> 非指针用.懂的都懂

那我们复习完了,之后我们直接将这段程序放在C++程序里面跑

会发现只有警告,但是没有报错,所以为什么说C++是C的延伸,是有道理的,紧密联系的

这个警告告诉我们需要将char *型转换成string型

终上所述C++是处理字符串的首选方案,所以我们要将char * 转换成 string

这个就是C++用类的概念整体实现C语言的结构体的功能

因为我们要将char *型转换为string 所以要包含头文件,iostream和命名空间std,,看我们的toy和car就要转换为类了加个class关键字在前面表示类,我们依旧是用了char address[20]数组的表示形式和string address 这两种形式,然后我们的函数指针的参数也很好理解,就是大概经历了这样的过程,这个是针对第一种用数组的情况的,就是怕后面回头看的时候理解不了,我要说明一下

解释代码: 我们这边toy babi 是什么意思呢??其实就是toy类的一个实例化对象,有句话说:类是对象的模板,对象是类的实例。但是我们这个不像是c语言之前的结构体是要写struct toy babi ,在C++里面类的对象是不用的,直接写成toy babi 就好了

诶,我们发现为啥我babi对象和BMW对象里的address和name还有date为啥呢都是报错,为什么呢??

其实就是因为结构体和类的区别了:

原因:在 C++ 中,类(class)的成员默认是private,而结构体(struct)的成员默认是public。如果你在class toy中没有显式声明public:,那么所有成员(包括address)都会被视为private,外部代码无法直接访问。所以要在类里面加上public,才能让我们在外部的对象进行使用我们类内部的代码

接下来就是看到我们的toy babi 因为在toy类中数据还是用char型数组定义的,所以我们在babi作为对象,依然要用strcpy这样才能进行复制写入值,最重要的是C++的字符串拼接了,因为我们想要用c++的写法来写代码,但是我们的又是数组定义的数据还是char 型,不是string类型定义的,所以我们需要强转

那为什么后面的不需要强转呢??

因为C++ 字符串拼接是从左到右进行的,且具有类型传染性

所以其实后面的也是转换了的

这个就是字符串拼接的写法

string str2 ="车的出厂地址为"+BMW.address+"名字为"+BMW.name+"出厂日期为"+BMW.date;

随后我们用cout输出str2就好啦

然后我们看到car BMW这个类的数据定义就是用string类型进行定义的,所以在字符串拼接的时候正常写就好了

重要的是第三个要注意了

 car *Audi =new car ();

这个大家猜是为什么要这样写?

因为这个对应着我们的c语言那边的不就是定义成的指针类型的数据嘛,那么在c语言我们是不是要进行开辟空间,我们c语言用的是malloc,那么在这边我们用new

  • new 是 C++ 的内存分配方式,会自动初始化对象,与 delete 配对。
  • malloc() 是 C 的内存分配方式,仅分配内存,需手动初始化,与 free() 配对。

其他的就是上面讲的内容了

补充一点,就是如果我们的不是string类型的,我们需要用到字符串拼接的话就需要转换了用std::to_string()函数  就像这个int count 计算出厂的车辆数目


网站公告

今日签到

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