广东网站建设模版,wordpress添加发布视频教程,哈尔滨做网站建设,网站模板开发主要作用今日碎碎念#xff1a;我在学C语言时经常用到结构体struct#xff0c;之后在写C程序时遇到在struct中定义构造函数和成员函数的情况#xff0c;这在c语言中是从未遇到过的#xff0c;觉得奇怪#xff0c;想到之前并没有真正系统学习C里的struct#xff0c;有必要今天详细…今日碎碎念我在学C语言时经常用到结构体struct之后在写C程序时遇到在struct中定义构造函数和成员函数的情况这在c语言中是从未遇到过的觉得奇怪想到之前并没有真正系统学习C里的struct有必要今天详细记录一下。 虽然今天结构体较少使用但知道它们是什么以及如何使用它们仍然很重要这并不仅仅是因为可以在较老的程序中遇到它们还因为在某些情况这里请看二、C class和struct的区别下类的实例无法使用这时必须使用结构体。
目录
一、C struct的用法 1、struct是什么 2、 struct的4种声明定义方式 3、结构体的2种初始化方式 4、结构体成员的访问 5、结构体的嵌套 6、将结构体作为参数和返回值
二、C class和struct的区别
三、C struct和 c struct的区别
四、struct计算结构体某个成员相对于结构体基址的偏移 一、C struct的用法 1、struct是什么 struct是程序员定义的数据类型将逻辑上连接在一起的不同类型的数据组合到一起的单元。 2、 struct的4种声明定义方式 a. 第一种语法表示 struct 结构体名称 { 数据类型 member1; 数据类型 member2; }
#includeiostream
#include string
using namespace std;
struct SStudent
{int nNo;std::string strName;
};int main(int argc, char *argv[])
{//使用初始化列表初始化structstruct SStudent s1 { 1, ying}; //C定义struct变量时前面的struct可以写SStudent s2 { 2, Ming}; //C定义struct变量时前面的struct也可以不写cout s1.nNo endl;cout s1.strName endl;cout s2.nNo endl;cout s2.strName endl;return 0;
}b.第二种语法表示 typedef struct 结构体名称{ 数据类型 member1 数据类型 member2; }结构体名称别名; 这种情况使用typedef关键字声明了数据类型的别名所以在定义结构体 变量时有两种方式 第一种结构体名称 构体变量名 第二种结构体名称别名 结构体变量名
#includeiostream
#include string
using namespace std;typedef struct SStudent
{int nNo;std::string strName;
} SStud;int main(int argc, char *argv[])
{SStudent s1 { 1, ying}; //使用结构体名称SStud s2 { 2, Ming}; //使用结构体名称别名cout s1.nNo endl;cout s1.strName endl;cout s2.nNo endl;cout s2.strName endl;return 0;
}c.第三种语法表示 struct 结构体名称{ 数据类型 member1 数据类型 member2; }结构体变量
#includeiostream
#include string
using namespace std;
struct SStudent
{int nNo;std::string strName;
} stu;int main(int argc, char *argv[])
{
// stu s2; //错误没有使用typedef关键字stu是变量不是类型stu { 1, ying}; //使用初始化表赋值stu.nNo 2; //修改成员nNo值stu.strName XiaoMing;//修改成员strName值cout stu.nNo endl;cout stu.strName endl;return 0;
}d.第四种语法表示 //匿名结构体 struct { 数据类型 member1 数据类型 member2; }结构体变量名; 在声明的同时定义了结构体变量但不能在其它地方声明因为我们无法得知该结构体的标识符所以就无法通过标识符来声明变量。
#includeiostream
#include string
using namespace std;//声明了结构体并定义且只能在这里定义了两个该结构体的变量
//由于无法获取结构体名称因为匿名所以无法在其他地方定义该结构体变量
struct
{int nNo;std::string strName;
} stu1, stu2;int main(int argc, char *argv[])
{ stu1 { 1, ying}; //使用初始化表赋值stu2 { 2, Ming}; //使用初始化表赋值cout stu1.nNo endl;cout stu1.strName endl;cout stu2.nNo endl;cout stu2.strName endl;return 0;
}3、结构体的2种初始化方式 a. 使用初始化列表 语法 //初始化列表中的项目是按照结构体声明中成员的顺序依次赋值各个成员的赋值用逗号分隔并用大括号括起来 结构体类型 变量名 {member1取值member2取值member3取值...}; 前面的例子都使用了初始化列表来初始化这里不再记录例子。 几个注意点 1使用初始化列表时可以仅仅初始化部分成员如果某个成员未被初始化则所有跟在它后面的成员都需要保留为未初始化。C未提供跳过某个成员初始化其他成员的方法。
#includeiostream
#include string
using namespace std;//声明了结构体增加nAge成员并且定义了两个变量stu1和stu2
struct SStudent
{int nNo;std::string strName;int nAge;
} stu1, stu2;int main(int argc, char *argv[])
{ stu1 { 1, ying}; //合法仅初始化了nNo和strName,不初始化nAge
// stu2 { 2, 11}; //非法不能跳过strName给nAge赋值cout stu1.nNo endl;cout stu1.strName endl;cout stu1.nAge endl;cout stu2.nNo endl;cout stu2.strName endl;cout stu2.nAge endl;return 0;
}2可以在结构体声明中使用默认值初始化结构体成员。
#includeiostream
#include string
using namespace std;//声明了结构体并且定义了两个变量stu1和stu2
struct SStudent
{int nNo 1;std::string strName YunCai;int nAge 6;
} stu1, stu2;int main(int argc, char *argv[])
{ stu1 { 2, ying}; //不给nAge赋值将取值默认值6cout stu1.nNo endl;cout stu1.strName endl;cout stu1.nAge endl;cout stu2.nNo endl; //不给stu2赋值所有成员都使用默认值cout stu2.strName endl;cout stu2.nAge endl;return 0;
}运行结果 b. 使用构造函数 与类构造函数一样结构体的构造函数必须是与结构体名称相同的公共成员函数并且没有返回类型。因为默认情况下所有结构体成员都是公开的所以不需要使用关键字 public。
#includeiostream
#include string
using namespace std;//声明了结构体
//并且定义了一个带有三个默认参数的构造函数
//在定义SStudent 变量而不向其传递任何参数时提供默认值
struct SStudent
{int m_nNo;string m_strName;int m_nAge;SStudent(int nNo 1, string strName YunCai, int nAge 6){m_nNo nNo;m_strName strName;m_nAge nAge;}
};int main(int argc, char *argv[])
{ SStudent stu1; //调用构造函数并且使用默认参数SStudent stu2(2, ying); //调用构造函数并传参nNo 2, strName yingcout stu1.m_nNo endl;cout stu1.m_strName endl;cout stu1.m_nAge endl;cout stu2.m_nNo endl;cout stu2.m_strName endl;cout stu2.m_nAge endl;return 0;
}4、结构体成员的访问 结构体数据成员都是public的所以它们可以被直接访问并且可以像常规变量一样使用。
结构体变量使用点运算符.访问数据成员结构体指针使用-指针运算符访问数据成员。
#includeiostream
#include string
using namespace std;struct SStudent
{int m_nNo;string m_strName;int m_nAge;SStudent(int nNo 1, string strName YunCai, int nAge 6){m_nNo nNo;m_strName strName;m_nAge nAge;}
};int main(int argc, char *argv[])
{ SStudent stu1; //调用构造函数并且使用默认参数SStudent stu2(2, ying); //调用构造函数并传参nNo 2, strName yingSStudent* stu3 new SStudent(3, Ming, 8); //使用new初始化SStudent对象指针cout stu1.m_nNo endl;//使用点运算符访问cout stu1.m_strName endl;cout stu1.m_nAge endl;cout stu2.m_nNo endl;cout stu2.m_strName endl;cout stu2.m_nAge endl;cout stu3-m_nNo endl;//使用指针运算符访问cout stu3-m_strName endl;cout stu3-m_nAge endl;delete stu3;stu3 nullptr;return 0;
}5、结构体的嵌套
就像一个类的对象可以作为成员放在另一个类中一个结构体的变量可以作为成员放在另一个结构体中。
#includeiostream
#include string
using namespace std;//声明了结构体SDate日期
struct SDate
{int m_nYear;int m_nMonth;int m_nDay;SDate(const int nY 2000, const int nM 11, const int nD 2){m_nYear nY;m_nMonth nM;m_nDay nD;}
};//声明了结构体SStudent学生,其中m_dateBirth是学生出生日期
struct SStudent
{int m_nNo;string m_strName;int m_nAge;SDate m_dateBirth;SStudent(const int nNo 1, const string strName YunCai,const int nAge 6, const SDate dateBirth SDate()){m_nNo nNo;m_strName strName;m_nAge nAge;m_dateBirth dateBirth;}
};//使用一个函数打印学生信息,参数类型为常量引用SStudent
void print(const SStudent stu)
{cout stu.m_nNo stu.m_strName stu.m_nAge ;cout Birthday: stu.m_dateBirth.m_nYear _ stu.m_dateBirth.m_nMonth _ stu.m_dateBirth.m_nDay endl;
}//修改学号增加100参数类型为值传递返回值为SStudent
SStudent UpdateNo1(SStudent stu)
{stu.m_nNo 100;return stu;
}//修改学号增加100参数类型为引用传递
void UpdateNo2(SStudent stu)
{stu.m_nNo 100;
}int main(int argc, char *argv[])
{ SStudent stu1; //调用构造函数并且使用默认参数print(stu1);stu1 UpdateNo1(stu1);print(stu1);SDate stu2_birthday(1999, 9, 10);SStudent stu2(2, Ying, 7, stu2_birthday);//调用够用构造函数并且传了4个参数print(stu2);UpdateNo2(stu2);print(stu2);return 0;
}运行结果 6、将结构体作为参数和返回值 a.将结构体作为参数与类对象一样结构体变量也可以通过值、引用和常量引用传递给函数。 1) 值传递需要生成整个原始结构的副本并传递给函数。因为不希望浪费时间来复制整个结构体所以除非结构很小否则一般会通过引用将结构体传递给函数。 2引用传递引用传递不会生成原始结构体的副本函数可以直接访问原始结构体的成员变量也可能更改它们。 3常量引用传递常量引用传递也不会生成原始结构体的副本函数直接访问原始结构体的成员变量但不能修改原始结构体的成员变量。
b.将结构体作为返回值函数的返回类型是结构体的名称。
在5、结构体的嵌套中的例子print函数使用了常量引用传递进行传值UpdateNo1函数的参数类型为值传递返回值为结构体UpdateNo2函数的参数类型为引用传递。
二、C class和struct的区别 结构体和类基本雷同唯一区别是类中成员变量默认为私有private而结构体中则为公有public。因此在使用时我们可以根据不同的场景或者需求来选择使用struct或者class。 a.这些情况下使用struct比class更好 1纯数据结构如果一个类只包含数据成员而没有成员函数 2)数据成员全部为public 3)用于C接口如果一个类需要与C语言交互例如作为C语言库的接口那么使用struct更加合适因为C语言不支持类的概念而使用struct可以更加方便地进行数据传递 4继承自C结构体如果一个类需要继承自一个C语言的结构体那么使用struct更加合适。因为C结构体默认为public并且在C中可以使用struct来继承。 b.这些情况下使用class比struct更好 1需要保证数据的安全性对数据的访问控制比较严格使用class可以将数据成员设置为私有成员private,防止外部直接修改数据 2需要进行多态如果一个类需要进行多态操作例如需要使用虚函数那么使用class更加合适。
三、C struct和 c struct的区别 a. C中定义结构体变量时可以省略struct但C语言中不可以省略 b. C中struct可以和类一样有访问权限并可以定义成员函数; C语言中struct没有访问权限的设置是一些变量的集合体不能定义成员函数 c.C中struct可以继承也可以实现多态C语言中struct不支持继承和多态
四、struct计算结构体某个成员相对于结构体基址的偏移
如何计算 #define offsetof(s,m) (size_t)(((s *)0)-m)
解释 ((s *)0):强制转化成数据结构指针,并使其指向地址0 ((s *)0)-m:使该指针指向成员m (((s *)0)-m):获取该成员m的地址 (size_t)(((s *)0)-m):转化这个地址为合适的类型
使用场景 offsetof已经被定义在系统库中所以直接使用offsetof计算结构体某个成员相对于结构体基址的偏移
例子 要计算如下SDate中m_nDay成员相对于结构体基址的偏移可以使用 offsetof(SDate, m_nDay)。 struct SDate{ int m_nYear; int m_nMonth; int m_nDay; }; 参考资料如下
1、C struct的4种定义方式_c struct 定义_Mr顺的博客-CSDN博客
2、C结构体完全攻略超详细
3、什么时候以struct 替代class - 知乎