引言
小伙伴们,在经过一些基础定义和指针,数组,函数的洗礼后,我相信大家肯定都已经对C++编程有了新的认知,同时呢,坚持下来的小伙伴们肯定都是好样的,大家都是很棒的,现在我们来学一学有关C++的最后一章,这章的难度比起指针和函数,还有数组,都还算简单,不过都是一些新概念,所以小伙伴们在学习的时候也要写好笔记,同时呢也要切身实地的亲手在VS上敲一敲,这样才能对知识有个消化吸收的过程。
好了,仍然是废话不多说,跟着小杨的节奏~冲冲冲!!!!!
自定义类型
引言:
很多时候,我们在写程序的时候一个变量里有很多小的变量,比如成绩里分为语文,数学,英语等,我们需要一个一个的把变量初始化,并每次调用的时候都需要找到正确的位置和函数。这对于看重计算速度的程序员们来说,很不方便,那有什么方式可以让我们可以更好的管理吗。
由此,在C++中,除了一些基本类型,我们在这引入一个新的可以有用户定义的数据类型。它就是“结构体”(struct),它允许你将多个不同或相同类型的数据项组合成一个单一的实体。这可以帮助你组织数据,使其更加模块化和易于管理。
结构类型
相关知识点:
- 结构类型也称结构体,可以使用结构变量来保存复杂数据。
- 结构变量的初始化分为顺序初始化,指定成员初始化。
- 可以通过“.”来访问结构变量中的成员
- 结构类型允许使用嵌套,结构类型中可以使用其他的结构类型
- 结构指针可以使用->直接使用其指向的结构变量的成员。
- 结构变量的定义和使用
#include <iostream>
using namespace std;
// 定义结构类型
struct Student
{
int no; // 学号
char gender; // 性别
float score; // 成绩
} s3; // 定义结构的同时,定义结构变量
void info(Student s);
int main()
{
// 定义结构变量
Student s1, s2;
// 指定成员初始化
s1.gender = 'f';
s1.no = 10000;
s1.score = 99.1;
info(s1);
// 顺序初始化
s2 = { 10001, 'm', 91.1};
s3 = { 10002, 'm', 92.1 };
info(s2);
info(s3);
return 0;
}
void info(Student s)
{
cout << "学号: " << s.no << " 性别: " << s.gender << " 成绩:" << s.score << endl;
}
- 结构类型嵌套
#include <iostream>
using namespace std;
// 结构类型嵌套
struct Date
{
int year;
int month;
int day;
};
struct Student
{
int no; // 学号
char gender; // 性别
float score; // 成绩
Date birth; // 生日
// 不允许使用结构体本身 Student s;
};
void info(Student s);
int main()
{
// 定义结构变量
Student s1, s2;
// 指定成员初始化
s1.gender = 'f';
s1.no = 10000;
s1.score = 99.1;
s1.birth.month = 10;
s1.birth.year = 2000;
s1.birth.day = 1;
info(s1);
// 顺序初始化
s2 = { 10001, 'm', 91.1, {2000, 1, 1} };
info(s2);
return 0;
}
void info(Student s)
{
cout << "学号: " << s.no << " 性别: " << s.gender << " 成绩:" << s.score ;
cout << " 出生日期:" << s.birth.year << "-" << s.birth.month << "-" << s.birth.day << endl;
}
- 简洁名称
#include <iostream>
using namespace std;
// 使用typedef定义结构类型的简洁名称
typedef struct Student
{
int no; // 学号
char gender; // 性别
float score; // 成绩
} stu1, stu2; // 定义结构变量的同时定义简洁名称
void info(Student s)
{
cout << "学号: " << s.no << " 性别: " << s.gender << " 成绩:" << s.score << endl;
}
// 定义带参函数info(s),参数是结构体类型,返回值是void型;
// 声明结构类型时使用typedef定义简洁名称
typedef struct Dog
{
int age;
int type;
}D;
void info2(Dog g)
{
cout <<"小狗的年龄是"<< g.age<<"岁。 小狗的种类是" << g.type << endl;
}
int main()
{
stu1 s1 = {1000, 'f', 99.9};
stu2 s2 = { 1001, 'm', 99.0 };
info(s1);
info(s2);
D d1 = { 1,23};
info2(d1);
}
- 结构数组
#include <iostream>
using namespace std;
struct Student
{
int no; // 学号
char gender; // 性别
float score; // 成绩
};
void info(Student s)
{
cout << "学号: " << s.no << " 性别: " << s.gender << " 成绩:" << s.score << endl;
}
int main()
{
// 定义结构数组
Student s[5] = {
{1000, 'f', 80.1},
{1001, 'm', 89.1},
{1002, 'f', 99.1},
{1003, 'm', 70.1},
{1004, 'f', 92.1},
};
// 获取成绩最高的同学的学号
Student s1 = s[0];
cout << "&s1" << &s1 << endl;
for (int i = 0; i < 5; i++)
{
if (s[i].score > s1.score)
{
s1 = s[i];
cout << "&s1" << &s1 << endl;
}
}
info(s1);
}
- 结构指针
#include <iostream>
using namespace std;
struct Student
{
int no; // 学号
char gender; // 性别
float score; // 成绩
};
void info(Student s)
{
cout << "学号: " << s.no << " 性别: " << s.gender << " 成绩:" << s.score << endl;
}
float average(Student* p, int n);
int main()
{
// 定义结构数组
Student s[5] = {
{1000, 'f', 80.1},
{1001, 'm', 89.1},
{1002, 'f', 99.1},
{1003, 'm', 70.1},
{1004, 'f', 92.1},
};
// 获取成绩最高的同学的学号
Student* s1 = s;
for (int i = 0; i < 5; i++)
{
// 结构指针可以使用->直接访问其指向的结构变量的成员
if (s[i].score > s1->score)
{
// &s[i] : &(*(s + i))
s1 = (s + i); // 通过指针算数运算符获取地址
}
}
info(*s1);
cout << average(s, 5) << endl;
cout << "sizeof(Student): " << sizeof(Student) << endl;
return 0;
}
float average(Student* p, int n)
{
float sum = 0;
for (int i = 0; i < n; i++)
{
sum += (p + i) -> score;
}
return sum / n;
}
联合类型
- 联合可以使几个不同变量占用同一内存空间。联合类型也称共同体
#include <iostream>
using namespace std;
// 定义联合类型
// 联合类型就是所有元素都指向一个变量,变量改变一个,其他的都跟着变
union my_data
{
int i;
char c;
float f;
};
int main()
{
cout << "sizeof(my_data): " << sizeof(my_data) << endl;
// 定义联合类型变量
my_data m;
// 使用联合类型变量
m.i = 97;
cout << "m.c: " << m.c << endl;
cout << "m.f: " << m.f << endl;
m.c = 'b';
cout << "m.i: " << m.i << endl;
cout << "m.f: " << m.f << endl;
}
结构和联合的区别
- 结构类型:多个变量有独立的存储空间,一个变量改变了,其他变量不跟着改变。
- 联合类型:多个变量共享存储空间,一个变量改变了,其他变量也跟着改变。
枚举
- 枚举是用标识符表示的整数型常量的集合。
#include <iostream>
using namespace std;
// 定义枚举类型
enum weekdays {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; // 枚据类型默认从0开始, 0, 1, 2, 3, 4, 5, 6
/*
枚据类型各元素不能同名。
如果不指定枚举类型元素的值,将自动从0开始为各个元素设置初值,后面的元素依次递增1.
如果指定某个元素的值,则下一个元素如果没有指定值,就是上一个元素值加1。
enum weekdays { Sun , Mon, Tue = 7, Wed = 10, Thu, Fri, Sat };
*/
int main()
{
cout << "Sun: " << Sun << endl;
cout << "Mon: " << Mon << endl;
cout << "Tue: " << Tue << endl;
cout << "Wed: " << Wed << endl;
cout << "Thu: " << Thu << endl;
cout << "Fri: " << Fri << endl;
cout << "Sat: " << Sat << endl;
int day = 1;
switch (day)
{
case Sun:
cout << "星期日" << endl;
break;
case Mon:
cout << "星期一" << endl;
break;
default:
break;
}
return 0;
}
命名空间
随着程序规模不断扩大,处理名称冲突问题就越来越麻烦,为此C++引入一个新的机制,即命名空间(也叫名称空间)。
- 命名空间只能在全局范围内定义,命名空间允许嵌套。
- 一个命名空间可以用另一个命名空间作为别名。
- 使用域运算符::获取命名空间中的元素
- using namespace 命名空间,使用命名空间中所有的元素。
#include <iostream>
// using namespace 使用命名空间中所有的元素
using namespace std;
// 定义命名空间
namespace NS1
{
int a = 10;
void f1()
{
cout << "NS1::f1()" << endl;
}
// 命名空间允许嵌套
namespace NS2
{
int b = 10;
void f2()
{
cout << "NS2::f2()" << endl;
}
}
}
namespace NS3
{
int a = 30;
void f1()
{
cout << "NS3::f1()" << endl;
}
}
// 一个命名空间可以用另一个命名空间作为别名
namespace ns2 = NS1::NS2;
// 使用一个命名空间中所有的成员
using namespace NS3;
int main()
{
// 使用域运算符::获取命名空间中的元素
cout << NS1::a << endl;
NS1::f1();
NS1::NS2::f2();
cout << ns2::b << endl;
cout << a << endl;
f1();
return 0;
}
多文件组织
引言:
随着我们写的代码越来越多,程序越来越复杂,当我们面对大型复杂项目时,我们往往会把代码模块化分开,让小组内成员分工合作完成一个整体,而作为一个总程序,我们只有一个main函数,所以一些功能函数,还有一些其他变量我们会分在其他文件里写,再根据法则去链接整个文件组织,使其成为一个整体。这就是为什么我们看到的一些项目都是大包小包的原因,现在我们也来学习一下,如何利用多文件组织。
相关知识点:
- 头文件(.h),一般存放数据结构定义,函数声明,全局常量,类声明等。
- 源文件(.cpp),源文件存放函数实现,类方法实现,等各种功能的实现。
- 编译预处理指令
- 文件包含,#include<文件名>或#include “文件名”
- 宏定义,#define 标识符 字符串,如 #define PI 3.1415926等
- 条件编译, #ifndef #else #endif
示例展示:
代码示例:
我们先创建一个cpp源文件,并写下如下代码
Main.cpp
#include <iostream>
#include "Point.h"
#include "Rectangle.h"
#include "Circle.h"
using namespace std;
int main()
{
Point point1 = { 1, 1 };
Rectangle r = { point1, 2, 3 };
cout << area(r) << endl;
cout << perimeter(r) << endl;
Circle c = { point1, 3 };
cout << area(c) << endl;
cout << perimeter(c) << endl;
return 0;
}
Circle.cpp
#include "Circle.h"
const float PI = 3.1415926;
int area(Circle c)
{
return PI * c.radius * c.radius;
}
int perimeter(Circle c)
{
return 2 * PI * c.radius;
}
Rectangle.cpp
#include "Rectangle.h"
int area(Rectangle r)
{
return r.length * r.width;
}
int perimeter(Rectangle r)
{
return (r.length + r.width) * 2;
}
Circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include "Point.h"
struct Circle
{
Point center;
int radius;
};
int area(Circle c);
int perimeter(Circle c);
#endif
Point.h
/*
编译预处理指令,条件编译。
#ifndef 标识符
程序段1
#else
程序段2
#endif
*/
#ifndef POINT_H
#define POINT_H
struct Point
{
int x;
int y;
};
#endif
Rectangle.h
#ifndef Rectangle_H
#define Rectangle_H
#include "Point.h"
struct Rectangle
{
Point center;
int length;
int width;
};
// 声明计算矩形面积函数
int area(Rectangle r);
// 声明计算周长的函数
int perimeter(Rectangle r);
#endif
小伙伴们有关多文件组织的内容,可能只看代码和讲解并不能第一时间看懂,建议大家在学习的时候也看看视频资料,这方面小杨也在准备了,相信不久大家就可以相关链接。
结语
哇~,小伙伴们终于在半个多月的时间内,大家把有关C++的基础课学完了哟,撒花❀❀❀!!!小伙伴们一定要及时复习把最近学到的内容学到炉火纯青哟,稍后,小杨会给大家带来C++的进阶课程,面向对象编程,这是C++的又一大难点,如果大家的基础好的话,会在后边的课程中才能学的轻松,不然后边的内容就会磕磕绊绊。
好了,不管怎么说,大家都很棒,为自己鼓鼓掌!!!接下来也要加油呀!!!冲冲冲!!!