温故知新----封装(struct)
上次提到class是最常见的封装,今天发现别人开发的SDK里面有大量的结构体struct
转载:
1. https://blog.csdn.net/a_forever_dream/article/details/88843230 (直接简单)
2.(更为详细)https://blog.csdn.net/weixin_42018112/article/details/82429514?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2
3. https://blog.csdn.net/veryitman/article/details/89578484(提供了另一种初始化方法)
废话
struct是个很有用的东西呢!
进入正题
struct的用处是定义一个新的类型,而这个类型里面可以是各种各样的东西。
比如:
struct node{//定义一个新的类型叫node
int a;
int b[110];
char c;
double d;
};//别忘了分号,毕竟这是个语句呢
当然里面还可以放一些更厉害的东西,就像这个!
struct node{
int y(int p)
{
return p+1;
}
int z;
void add()
{
z++;//这个z和上面那个是同一个
}
};
定义的话直接用就行了,譬如:
node x;
需要调用里面的元素时,加个点就行了,就像这样:
x.a=10;
x.b[1]++;
x.c='a';
x.d=3.1415;
x.z=x.y(x.z);
x.add();
struct还有一个神奇的东西:构造函数
那有人可能会问,这比直接定义里面的元素好在哪里呢?
既然struct是把一些不相关的东西整合到一起,那么这些不相关的东西就有了某些神奇的联系,比如说可以用来定义线段树的顶点之类的。
看下面一段代码:
struct node{
node *zuo,*you;
int l,r,z;
void build(int ll,int rr)
{
l=ll,r=rr;z=0;
int mid=l+r>>1;
if(l==r)zuo=you=NULL;
else zuo=new node,zuo->build(ll,mid),you=new node,you->build(mid+1,rr);
}
};
这是利用指针和struct写的一个构建线段树的代码,可以说是很精简了。
并且还有一个很方便的功能:
node a,b;
a=b;//可以直接把b中所有东西直接丢给a
C++中的结构体
在C语言中,结构体不能包含函数。
在面向对象的程序设计中,对象具有状态(属性)和行为,状态保存在成员变量中,行为通过成员方法(函数)来实现。
C语言中的结构体只能描述一个对象的状态,不能描述一个对象的行为。在C++中,考虑到C语言到C++语言过渡的连续性,对结构体进行了扩展,C++的结构体可以包含函数,这样,C++的结构体也具有类的功能,与class不同的是,结构体包含的函数默认为public,而class中默认是private。
结构体的定义与声明
实例代码1:
struct tag
{
member-list
}variable-list;
注:struct为结构体关键字;
tag为结构体的标志;
member-list为结构体成员变量及成员函数列表,其必须列出其所有成员;
variable-list为此结构体声明的变量;
实例代码2:
#include <iostream>
using namespace std;
struct SAMPLE
{
int x;
int y;
int add() {return x+y;}
}s1;
int main()
{
cout<<"没初始化成员变量的情况下:"<<s1.add()<<endl;
s1.x = 3;
s1.y = 4;
cout<<"初始化成员变量的情况下:"<<s1.add()<<endl;
system("pause");
return 0;
}
=>没初始化成员变量的情况下:0
初始化成员变量的情况下:7
C++中的结构体与类的区别: (1)class中默认的成员访问权限是private的,而struct中则是public的。 (2)class继承默认是private继承,而从struct继承默认是public继承。
结构体也可以继承结构体或者类。
结构体的作用
在实际项目中,结构体是大量存在的。研发人员常使用结构体来封装一些属性来组成新的类型。由于C语言内部程序比较简单,研发人员通常使用结构体创造新的“属性”,其目的是简化运算。
结构体在函数中的作用不是简便,最主要的作用就是封装。封装的好处就是可以再次利用。让使用者不必关心这个是什么,只要根据定义使用就可以了。
请看转载的原文链接:https://blog.csdn.net/veryitman/article/details/89578484
本篇文章的所有代码都经 gcc-7 编译器编译过。关于在 macOS 中如何安装和使用 gcc,可以参考 GCC: Homebrew 安装 GCC 和 Binutils 这篇文章。
结构体成员指针的初始化
结构体成员指针的初始化,指的是初始化结构体中指针变量的成员。
我们举个例子,下面是 Animal 的结构体。
struct Animal {
char *name; //指针成员
int age;
char info[200]; //字符数组
struct Animal *nextAnimal; //指针成员
};
结构体 Animal 含有4个成员变量,其中 name、info 和 nextAnimal 是指针变量。
写一段测试代码,如下:
int main(int argc, const char *argv[])
{
struct Animal animal;
printf("animal's name: %s, age: %i, info: %s\n", animal.name, animal.age, animal.info);
return 0;
}
运行结果正常,终端输出如下:
animal's name: (null), age: 0, info:
1
我们来验证一下 Animal *nextAnimal 在没有初始化的情况下,会不会有什么问题。
int main(int argc, const char *argv[])
{
struct Animal animal;
printf("animal's name: %s, age: %i, info: %s\n", animal.name, animal.age, animal.info);
printf("animal.nextAnimal: %p\n", animal.nextAnimal);
printf("animal.nextAnimal->name: %s, age: %i, info: %s\n", animal.nextAnimal->name, animal.nextAnimal->age, animal.nextAnimal->info);
return 0;
}
程序编译没有问题,运行报错
animal's name: (null), age: 0, info:
animal.nextAnimal: 0x1127fa036
Segmentation fault: 11
修改一下代码,初始化一下 animal.nextAnimal 这个指针,如下:
int main(int argc, const char *argv[])
{
struct Animal animal;
printf("animal's name: %s, age: %i, info: %s\n", animal.name, animal.age, animal.info);
printf("animal.nextAnimal: %p\n", animal.nextAnimal);
// 初始化指针变量
animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
printf("animal.nextAnimal->name: %s, age: %i, info: %s\n", animal.nextAnimal->name, animal.nextAnimal->age, animal.nextAnimal->info);
return 0;
}
再次编译重新运行,还是报错。还需要初始化 animal.nextAnimal->name 这个变量。
int main(int argc, const char *argv[])
{
struct Animal animal;
printf("animal's name: %s, age: %i, info: %s\n", animal.name, animal.age, animal.info);
printf("animal.nextAnimal: %p\n", animal.nextAnimal);
// 初始化指针变量
animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
// 初始化 name 变量
animal.nextAnimal->name = "cat";
printf("animal.nextAnimal->name: %s, age: %i, info: %s\n", animal.nextAnimal->name, animal.nextAnimal->age, animal.nextAnimal->info);
return 0;
}
编译运行,一切正常。
animal's name: (null), age: 0, info:
animal.nextAnimal: 0x10f0f1036
animal.nextAnimal->name: cat, age: 0, info:
123
通过上面的例子,结构体指针变量有些会给默认值,有些又不会给,所以都要初始化指针变量。
修改一下代码,示例如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Animal {
char *name; //指针成员
int age;
char info[200]; //字符数组
struct Animal *nextAnimal; //指针成员
};
int main(int argc, const char *argv[])
{
struct Animal animal;
animal.name = "cat";
strcpy(animal.info, "This is a cat.");
printf("animal's name: %s, age: %i, info: %s\n", animal.name, animal.age, animal.info);
printf("animal.nextAnimal: %p\n", animal.nextAnimal);
// 初始化指针变量
animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
// 初始化变量
animal.nextAnimal->name = "cat";
strcpy(animal.nextAnimal->info, "This is a cat.");
printf("animal.nextAnimal->name: %s, age: %i, info: %s\n", animal.nextAnimal->name, animal.nextAnimal->age, animal.nextAnimal->info);
return 0;
}
结构体指针的初始化
指的是初始化结构体指针变量。
int main(int argc, const char *argv[])
{
struct Animal *ptAnimal;
printf("ptAnimal's name: %s, age: %i, info: %s\n", ptAnimal->name, ptAnimal->age, ptAnimal->info);
return 0;
}
编译运行报错:
Segmentation fault: 11
1
同样的道理,需要初始化指针变量。完成后的示例代码如下:
int main(int argc, const char *argv[])
{
struct Animal *ptAnimal;
// 初始化结构体指针
ptAnimal = (struct Animal *)malloc(sizeof(struct Animal));
ptAnimal->name = "dog";
strcpy(ptAnimal->info, "This is a big dog");
printf("ptAnimal's name: %s, age: %i, info: %s\n", ptAnimal->name, ptAnimal->age, ptAnimal->info);
// 初始化结构体指针的成员指针变量 nextAnimal
ptAnimal->nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
ptAnimal->nextAnimal->name = "dog";
strcpy(ptAnimal->nextAnimal->info, "This is a big dog");
printf("ptAnimal->nextAnimal's name: %s, age: %i, info: %s\n",
ptAnimal->nextAnimal->name, ptAnimal->nextAnimal->age, ptAnimal->nextAnimal->info);
return 0;
}
完整示例
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Animal {
char *name; //指针成员
int age;
char info[200]; //字符数组
struct Animal *nextAnimal; //指针成员
};
int main(int argc, const char *argv[])
{
/// 验证结构体指针成员变量
{
struct Animal animal;
animal.name = "cat";
strcpy(animal.info, "This is a cat.");
printf("animal's name: %s, age: %i, info: %s\n", animal.name, animal.age, animal.info);
printf("animal.nextAnimal: %p\n", animal.nextAnimal);
// 初始化指针变量
animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
// 初始化变量
animal.nextAnimal->name = "cat";
strcpy(animal.nextAnimal->info, "This is a cat.");
printf("animal.nextAnimal->name: %s, age: %i, info: %s\n", animal.nextAnimal->name, animal.nextAnimal->age, animal.nextAnimal->info);
}
/// 验证结构体指针
{
struct Animal *ptAnimal;
// 初始化结构体指针
ptAnimal = (struct Animal *)malloc(sizeof(struct Animal));
ptAnimal->name = "dog";
strcpy(ptAnimal->info, "This is a big dog");
printf("ptAnimal's name: %s, age: %i, info: %s\n", ptAnimal->name, ptAnimal->age, ptAnimal->info);
// 初始化结构体指针的成员指针变量 nextAnimal
ptAnimal->nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
ptAnimal->nextAnimal->name = "dog";
strcpy(ptAnimal->nextAnimal->info, "This is a big dog");
printf("ptAnimal->nextAnimal's name: %s, age: %i, info: %s\n",
ptAnimal->nextAnimal->name, ptAnimal->nextAnimal->age, ptAnimal->nextAnimal->info);
}
return 0;
}
编译
gcc-7 main.c -o main
1
运行
./main
1
运行结果如下:
animal's name: cat, age: 0, info: This is a cat.
animal.nextAnimal: 0x0
animal.nextAnimal->name: cat, age: 0, info: This is a cat.
ptAnimal's name: dog, age: 0, info: This is a big dog
ptAnimal->nextAnimal's name: dog, age: 0, info: This is a big dog
————————————————
温故知新----封装(struct)的更多相关文章
- C++实现大数据乘法
结构体定义与封装 struct bigdatacom { private : ]; ]; public : void init(const char *str1,const char *str2) { ...
- IPSEC实现
IPSEC介绍与实现 一.介绍 IPSec 协议不是一个单独的协议,它给出了应用于IP层上网络数据安全的一整套体系结构,包括网络认证协议 Authentication Header(AH).封装安全载 ...
- Golang全接触
满打满算, 从好友推荐Golang至发文时, 使用Golang已经有1年多了. 这种时间对于C/C++ Java这些老者来说, 简直是菜鸟级别的经验 但作为新生代语言的特点就是实战. Golang这一 ...
- 跟着内核学框架-从misc子系统到3+2+1设备识别驱动框架
misc子系统在Linux中是一个非常简单的子系统,但是其清晰的框架结构非常适合用来研究设备识别模型.本文从misc子系统的使用出发,通过了解其机制来总结一套的设备识别的驱动框架,即使用使用同一个驱动 ...
- linux设备驱动之字符设备驱动模型(1)
一:字符设备驱动 在linux下面,应用层看到的一切皆为文件(名字)所有的设备都是文件,都可以调用open,read,write来操作,而在内核中每个中每个设备有唯一的对应一个设备号: APP ( ...
- Solidity高级理论(二):Gas
solidity高级理论(二):Gas 关键字:Gas.结构体.节省小技巧 Gas是什么 在Solidity中,用户想要执行DApp都需要支付一定量的Gas,Gas可以用以太币购买,所以,用户每次使用 ...
- 【Android休眠】之PowerKey唤醒源实现【转】
转自:https://blog.csdn.net/u013686019/article/details/53677531 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog ...
- Android Native层异步消息处理框架
*本文系作者工作学习总结,尚有不完善及理解不恰当之处,欢迎批评指正* 一.前言 在NuPlayer中,可以发现许多类似于下面的代码: //============================== ...
- 学习笔记之C++入门到精通(名师教学·手把手教会)【职坐标】_腾讯课堂
C++入门到精通(名师教学·手把手教会)[职坐标]_腾讯课堂 https://ke.qq.com/course/101465#term_id=100105503 https://github.com/ ...
随机推荐
- 使用intellij IDEA远程连接服务器部署项目
由于不想每次打开上传的文件软件,故研究使用intellij IDEA集成 ,下面是我使用的过程的一些记录. 使用intellij 远程连接服务器连接Linux服务器部署项目,方便我们开发测试. 本人使 ...
- 使用echarts 轻松搞定各种后台数据统计
之前接到老大一个需求,需要将公私生态系统构建一个日志系统,统计公有云.私有云还有其他工具平台(如禅道,jenkins)的用户登录信息,并使用图标的形式动态显示,之前刚入门的时候接触过echarts 这 ...
- 【Android】Android开发实现带有反弹效果,仿IOS反弹scrollview详解教程
作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 首先给大家看一下我们今天这个最终实现 ...
- Springboot整合Spring Cloud Kubernetes读取ConfigMap,支持自动刷新配置
1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Docker & Kubernetes相关文章:容器技术 之前介绍了Spring Cloud Config的用法,但 ...
- JS 进制转换的理解
该事情的由来是来自于一个面试题,题目是这样的,[1,2,3].map(parseInt)的结果是什么? 作为菜鸟的我们一定是觉得分别把1,2,3分别交给parseInt,无非就是1,2,3嘛.其实结果 ...
- 答应我,用了这个jupyter插件,别再重复造轮子了
1 简介 在使用Python.R等完成日常任务的过程中,可能会经常书写同样或模式相近的同一段代码,譬如每次使用matplotlib绘制图像的时候可以在开头添加下面两行代码来解决中文乱码等显示问题: p ...
- Activiti7 绑定业务主键以及流程定义 流程实例的挂起和激活
绑定业务主键businessKey /** * 绑定业务主键 */ @Test public void bindingBusinessKey() { // 获取RuntimeService Runti ...
- EasyPoi导出Excel
这几天一直在忙工作中的事情,在工作中有一个问题,可能是因为刚开始接触这个EasyPoi,对其也没有太多的理解,在项目中就使用了,有一个需求,是要导出项目中所有的表格,今天就对这个需求进行分析和实现吧; ...
- stackoverflow的ret2syscall利用
ret2syscall 系统调用 ret2syscall,即控制程序执行系统调用,获取shell.Linux将内核功能接口制作为系统调用(system call),可在程序中直接调用.程序中存在int ...
- 关于Nginx mmap(MAP_ANON|MAP_SHARED, 314572800)报错
mmap 报错解决 今天修改了一下测试环境的Nginx的nginx.conf,然后做检测的时候报了一个错误 /usr/local/bin/nginx -c /usr/local/etc/openres ...