当前位置: 首页 > news >正文

C++ 结构体

什么是结构体

结构体是一个由程序员定义的数据类型,可以容纳许多不同的数据值。在过去,面向对象编程的应用尚未普及之前,程序员通常使用这些从逻辑上连接在一起的数据组合到一个单元中。一旦结构体类型被声明并且其数据成员被标识,即可创建该类型的多个变量,就像可以为同一个类创建多个对象一样


结构体声明

声明结构体的方式和声明类的方式大致相同,其区别如下

  1. 使用关键字 struct 而不是关键字 class
  2. 尽管结构体可以包含成员函数,但它们很少这样做。所以,通常情况下结构体声明只会声明成员变量。
  3. 结构体声明通常不包括 public 或 private 的访问修饰符
  4. 类成员默认情况是私有的,而结构体的成员则默认为 public 程序员通常希望它们保持公开,只需使用默认值即可

以下是一个结构体声明的示例

struct PayRoll 这个特殊结构体的名称是 PayRoll。请注意,它以大写字母开头,这和类名使用大写字母开头的约定一样
{
	结构体中可以指定 任意数量 任意类型的 结构体变量
    int empNumber;
    string name;
    double hours,payRate,grossPay;
}PR;与类声明一样,在结构体声明的大括号后面必须有一个分号

可以看出 此结构体 将 5 个变量绑定在一起 保存了员工的工资单数据

和类对象被创建之前 类声明不会被实例化用于 结构体声明(指PayRoll)不会创建任何结构体的示例 此示例中的结构体声明
只是告诉编译器 PayRoll结构体的参数构造 本质上PayRoll只是一个新数据类型 还需指定结构体变量(指PR) 才能使用此结构体


关于结构体变量的指定方法

方法一 结构变量声明

struct PayRoll lisi;

方法二 声明结构变量时省略关键字

PayRoll zhangsan;

方法三 在定义结构后面声明

struct PayRoll 
{
XXXXXXXXXXXXXX
}wangmazi;

上述的结构体变量每一个都是 PayRoll 结构体的实例,可以被分配和拥有自己的内存 以保存其成员数据
注意 :尽管 3 个结构体变量具有不同的名称,但每个变量都包含具有相同名称的成员


初始化结构体

当定义结构体变量时,可以通过两种方式初始化它:使用初始化列表构造函数进行初始化


初始化列表

初始化列表时最简单的方法 初始化列表用于初始化一组 内存位置的值列表 列表中的项目使用逗号分割并用大括号进行包装

例如 我们已经声明了一下IDmation结构体

struct IDmation
{
	//声明三个成员变量 
	string name;
	string ID;
	char sexual;
};

定义和初始化IDmation的方式是 先指定变量名 后接赋值运算符初始化列表 如下所示

IDmation IDinit = {"TylerDurden","real*real*real",'M'};

该声明定义IDinit是一个IDmation结构体的变量 大括号内的值 按顺序分配给结构体内的成员 所以IDinit的数据成员已初始化


除了初始化所有成员 也可以初始化结构体变量的部分成员 例如 如果仅知道结构体变量"name"的信息 但不知"ID"和"sexual"的信息 则可以按以下方式定义和初始化变量

IDmation IDinit = {"TylerDurden'};

这里只有name成员被初始化 "ID"和"sexual"未被初始化
注意:

  1. ** C++不提供跳过成员的初始化方法** 也就是说 虽然可以不对所有变量进行初始化 但是初始化的方法必须从左侧第一个变量名开始 且不能 跳过任何一个变量名
  2. 不可以在结构体声明中初始化结构因为结构体声明只是创建一个新的数据类型 还不存在这种类型的变量
    因为结构体声明只声明一个结构体“看起来是什么样子的”,所以不会在内存中创建成员变量。只有通过定义该结构体类型的变量来实例化结构体,才有地方存储初始值

构造函数初始化结构体

因为初始化列表有两个缺点

  1. 如果有某个成员未被初始化 跟随在其后的成员都不能被初始化
  2. 如果结构体包含任何诸如字符串之类的对象 在许多编译器上他都将无法运行(VS实测是可以的)

使用构造函数来初始化结构体成员变量可以避免这两种情况的发生 与类构造函数一样 结构体的构造函数必须是与结构体名称相同的公共成员函数 并且没有返回类型 因为在默认情况下 所有结构体成员都是公开的 所以不需要使用关键字public

使用一个名为 Employee 的结构体内部声明语句,它包含一个具有两参数的构造函数,以便在创建一个 Employee 结构体变量而不向其传递任何参数时,提供默认值

struct IDmation
{
	//声明三个成员变量 
	string name;
	string ID;
	char sexual;
	IDmation(string n = "JamesDean", string i = "12345A")//名为 Employee 的结构体内部声明语句(构造函数)
	{
		//用构造函数中的参数初始化结构体
		name = n;
		ID = i;
	}
}IDinit;//还需设置结构体变量才可使用

结果
在这里插入图片描述


访问结构体成员

结构体成员的访问方式和类的公共成员一样 都是使用 . 点 运算符(当结构体对象为指针类型时 使用->指向符) 但类的数据成员通常是私有的必须通过类函数进行访问 而结构数据成员是公共的 所以他们可以被直接访问 并且可以像常规变量一样使用

以下语句为前面创建的每个IDmation结构体的IDinit结构体变量进行赋值

IDinit.name = "TaylerDurden";
IDinit.ID = "do not talk about fight club";
IDinit.sexual ='M';
cout << IDinit.name <<"  "<< IDinit.ID << "  " << IDinit.sexual <<"  "<<endl;

结果在这里插入图片描述
在 cin 语句、cout 语句和数学运 算中,单个结构体成员的用法和常规变量基本上是一样的


结构体嵌套

正如一个类的对象可以嵌套在另一个类中一样 一个结构体的实例也可以嵌套在另一个结构体中
例如以下声明

struct  Costs
{
	double wholesale;
	double retail;
};
struct Item
{
	string PartNum;
	string Description;
	Costs pricing;//对前方定义的结构体 Costs进行嵌套
}widget;

Costs结构体有 两 个double类型成员 wholesale 和 retail , Item 结构体有 三 个成员前两个是partNum 和 description,他们都是 Item 结构体内部的string类型的对象 第三个是pricing ,它是一个嵌套的Costs结构体
如果定义了一个名为widget的Item结构体 那么因为嵌套了Costs结构体的缘故 此时其成员为
在这里插入图片描述
访问结构体嵌套后的结构体成员

widget.PartNum = "123A";
widget.Description = "iron widget";
widget.pricing.wholesale = 100.0;
widget.pricing.retail = 150.0;

注意: ** wholesale 和 retail 不是 widget 的成员 ,pricing 才是,要访问 wholesale 和 retail,必须首先访问widget下的pricing**,由于他是一个Costs结构体 所以同样可以使用点运算符访问其wholesale 和 retail成员

对于所有结构体来说 访问成员是必须使用成员名称 而不是结构体名称 例如以下语句不合法

cout << widget.retail;    // 错误 未首先访问widget下的嵌套结构体变量名pricing
cout << widget.Costs.wholesale;    // 错误

正确输出方法

cout << widget.PartNum<<"    " << widget.Description << "    " << widget.pricing.wholesale << "    " << widget.pricing.retail << "    ";

结果
在这里插入图片描述


将结构体传递给函数

与类对象一样,结构体变量也可以通过值、引用 、常量引用传递给函数 默认情况下,它们通过值传递,这意味着需要生成整个原始结构的副本并传递给函数 。因为不希望浪费时间来复制整个结构体,所以,除非结构很小,否则一般会通过引用将结构体传递给函数 这样意味着函数可以访问原始结构的成员变量,从而可能更改它们。如果不想让函数更改任何成员变量值,那么可以考虑将结构体变量作为一个常量引用传递给函数


以下为函数传递结构体信息的示例代码

#include <iostream>
#include <windows.h>
#include <string.h>

using namespace std;

struct IDmation
{
	//声明三个成员变量 
	string name;
	string ID;
	char sexual;
	IDmation(string n = "JamesDean", string i = "12345A")//构造函数 
	{
		//用构造函数中的参数初始化结构体
		name = n;
		ID = i; 
	}
}IDinit;//还需设置结构体变量才可使用


void Data(IDmation& IDdata);
void ShowData(const IDmation& IDdata);

int main()
{
	IDmation data;
	Data(data);
	ShowData(data);
	return 0;
}

//todo将结构体传递给函数
void Data(IDmation &IDdata)//输入结构体变量参数函数 (可改变结构体中的参数)
{	
	cout << "输入姓名:";
	cin >> IDdata.name;
	cout << "输入ID:";
	cin >> IDdata.ID;
	cout << "输入sexual:";
	cin >> IDdata.sexual;
}

void ShowData(const IDmation& IDdata)//读取结构体参数函数 (结构体变量此时为静态常量 不可改变结构体中的参数)
{
	cout << "姓名为" << IDdata.name << endl;
	cout << "ID为" << IDdata.ID << endl;
	cout << "sexual为" << IDdata.sexual << endl;
}

可以看出结构体变量可以像任何变量一样被引用为形参 传输到任意函数中去 并可以读取写入结构体的数据

结果在这里插入图片描述


从函数返回一个结构体

在这种情况下,函数的返回类型是结构体的名称 首先用 BackData函数 设置 IDmation结构体为返回值,再在函数中建立一个IDmation结构体变量名Back 将结构体数据值放入其成员变量中,然后将其传递回 main,而不是将其作为引用变量从 main 接收


int main()
{
IDmation data;
data = BackData();在main函数中利用BackData()函数的返回值进行赋值
ShowData(data); //输出结构体成员变量函数
}

IDmation BackData()//返回结构体函数 返回值为IDmation结构体型
{	
	IDmation Back;//建立一个IDmation结构体变量名Back  将结构体数据值放入其成员变量中
	cout << "输入姓名:";
	cin >> Back.name;
	cout << "输入ID:";
	cin >> Back.ID;
	cout << "输入sexual:";
	cin >> Back.sexual;
	return Back;//从函数返回一个结构体Back 
}

效果在这里插入图片描述

源自-C++对象的基础(结构体)项目

本文来自http://c.biancheng.net/view/1407.html

全部代码

#include <iostream>
#include <windows.h>
#include <string.h>

using namespace std;

//todo定义一个结构体
//
//struct IDmation
//{
//	//声明三个成员变量 
//	string name;
//	string ID;
//	char sexual;
//};

//todo定义一个结构体并进行构造函数初始化结构体
struct IDmation
{
	//声明三个成员变量 
	string name;
	string ID;
	char sexual;
	IDmation(string n = "JamesDean", string i = "12345A")//构造函数 
	{
		//用构造函数中的参数初始化结构体
		name = n;
		ID = i; 
	}
}IDinit;//还需设置结构体变量才可使用


//todo结构体的嵌套
struct  Costs
{
	double wholesale;
	double retail;
};
struct Item
{
	string PartNum;
	string Description;
	Costs pricing;//对前方定义的结构体 Costs进行嵌套
	//由于结构体的嵌套 此时 Item结构体的成员对象为 string PartNum;  	string Description; 	double wholesale; double retail; 
}widget;

void Data(IDmation& IDdata);
void ShowData(const IDmation& IDdata);
IDmation BackData();
int main()
{
//	IDmation IDinit = { "TylerDurden"};

	//todo访问结构体成员
	IDinit.name = "TaylerDurden";
	IDinit.ID = "do not talk about fight club";
	IDinit.sexual ='M';
//	cout << IDinit.name <<"  "<< IDinit.ID << "  " << IDinit.sexual <<"  "<<endl;

	//todo访问结构体嵌套后的结构体成员
	widget.PartNum = "123A";
	widget.Description = "iron widget";
	widget.pricing.wholesale = 100.0;
	widget.pricing.retail = 150.0;
	//cout << widget.PartNum<<"    " << widget.Description << "    " << widget.pricing.wholesale << "    " << widget.pricing.retail << "    ";
	
	//todo将结构体传递给函数
	IDmation data;
	/*Data(data);
	ShowData(data);*/

	//todo函数返回一个结构体
	data = BackData();
	ShowData(data); 
	return 0;
}

//todo将结构体传递给函数
void Data(IDmation &IDdata)//输入结构体变量参数函数 (可改变结构体中的参数)
{	
	cout << "输入姓名:";
	cin >> IDdata.name;
	cout << "输入ID:";
	cin >> IDdata.ID;
	cout << "输入sexual:";
	cin >> IDdata.sexual;
}

void ShowData(const IDmation& IDdata)//读取并显示结构体参数函数 (结构体变量此时为静态常量 不可改变结构体中的参数)
{
	cout << "姓名为" << IDdata.name << endl;
	cout << "ID为" << IDdata.ID << endl;
	cout << "sexual为" << IDdata.sexual << endl;
}

//todo函数返回一个结构体
IDmation BackData()
{	
	IDmation Back;
	cout << "输入姓名:";
	cin >> Back.name;
	cout << "输入ID:";
	cin >> Back.ID;
	cout << "输入sexual:";
	cin >> Back.sexual;
	return Back;//从函数返回一个结构体
}

相关文章:

  • 中兴事业部你真行
  • C++ 对象的基础(结构及结构指针)
  • 《Linux内核设计与实现》读书笔记(三)- Linux的进程
  • C++联合枚举和类型别名
  • while循环与中断语句break、continue、return以及goto的使用
  • CentOS使用Screen管理会话选项
  • 循环程序跳出(_kbhit()、getch() 、getchar())
  • C++ 类与对象
  • (转) Android中ViewStub组件使用
  • C++ 构造函数与析构函数
  • MFC应用程序中处理消息的顺序,创建窗口的过程关闭窗口的顺序(非模态窗口),打开模式对话框的函数调用顺序...
  • C++ this指针 与 类的继承
  • OpenGL_Qt学习笔记之_07(闪烁的星星)
  • C++ 继承机制中的构造器与析构器
  • C#数组
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • exports和module.exports
  • JavaScript 基本功--面试宝典
  • jquery ajax学习笔记
  • linux学习笔记
  • Map集合、散列表、红黑树介绍
  • Promise面试题,控制异步流程
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • React-生命周期杂记
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 回顾2016
  • 你不可错过的前端面试题(一)
  • 判断客户端类型,Android,iOS,PC
  • 前端面试总结(at, md)
  • 如何用纯 CSS 创作一个货车 loader
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • #14vue3生成表单并跳转到外部地址的方式
  • #git 撤消对文件的更改
  • #在 README.md 中生成项目目录结构
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (四)图像的%2线性拉伸
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • (转载)从 Java 代码到 Java 堆
  • (轉貼) UML中文FAQ (OO) (UML)
  • ../depcomp: line 571: exec: g++: not found
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .net core控制台应用程序初识
  • .net 后台导出excel ,word
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .NET程序员迈向卓越的必由之路
  • .NET分布式缓存Memcached从入门到实战
  • .net中调用windows performance记录性能信息