4.面向对象-封装-成员变量和访问修饰符
4.1 知识点
知识回顾:类和对象
- 在
.h
结尾的头文件中声明类 - 在
.cpp
结尾的源文件中定义类 - 对于小型类或模板类,可直接在头文件中同时完成声明和定义
类的基本结构:
class 类名
{
// 访问修饰符(可省略)
// 构造函数、析构函数
// 特征 —— 成员变量
// 行为 —— 成员方法
// ……
};
对象(实例化)的声明:
引用头文件
#include "XXX.h"
普通对象(栈上)
类名 变量名; 类名 变量名 = 构造函数名(...);
指针对象(堆上)
类名* 变量名 = new 构造函数名(...);
引用对象
类名& 变量名 = 想要引用的对象;
成员变量
- 声明在类的语句块中,用于描述对象的特征
- 可以是任何变量类型,数量不做限制
- 是否在声明时赋值可根据需求决定(老版本 C++ 只能在构造函数中初始化)
- 不能有非指针类型的本类成员,否则会导致构造递归
示例:
#pragma once
enum E_SexType
{
Man,
Woman,
};
#pragma once
struct Position
{
int x;
int y;
Position(int x, int y) : x(x), y(y) {}
};
#pragma once
class Pet {};
#pragma once
#include <iostream>
#include "Pet.h"
#include "Position.h"
#include "E_SexType.h"
using namespace std;
//类和枚举以及结构体 都可以独立的在.h头文件中进行声明和定义 要使用的时候 引用头文件即可
class Person
{
//成员变量
//1.用来描述 人 这种对象的特征
//2.写在类语句块中
//3.可以是任意的变量类型
//4.数量不限制
//5.是否赋值根据需求定 如果有构造函数可以在其中初始化 如果没有建议 都赋值一个初始值
string name = "韬老狮";
int age = 18;
E_SexType sex = Man;
Position pos = Position(4,5);
//6.不能有非指针类型的自己类型的成员 否则 会出现构造函数递归
//Person gridFriend;
//Person friends[10];//数组也不行
Person* gridFriend = nullptr;
Person* friends[10] = { nullptr };
//如果不是自己类型的类 是可以声明非指针的
Pet pet = Pet();
Pet* pet2 = nullptr;
};
默认是私有的无法直接使用:
//没声明访问修饰符前类不能直接使用 会提示不可访问编译报错 结构体才可以
//Person person;
//person.name = "tao";
访问修饰符(3P)
- public:公共,内部和外部均可访问
- private:私有,仅类内部可访问(默认)
- protected:保护,对内部和子类开放,外部不可访问
示例:
#pragma once
#include <iostream>
#include "Pet.h"
#include "Position.h"
#include "E_SexType.h"
using namespace std;
//类和枚举以及结构体 都可以独立的在.h头文件中进行声明和定义 要使用的时候 引用头文件即可
class Person
{
//成员变量
//1.用来描述 人 这种对象的特征
//2.写在类语句块中
//3.可以是任意的变量类型
//4.数量不限制
//5.是否赋值根据需求定 如果有构造函数可以在其中初始化 如果没有建议 都赋值一个初始值
public:
string name = "韬老狮";
int age = 18;
E_SexType sex = Man;
Position pos = Position(4,5);
private:
//6.不能有非指针类型的自己类型的成员 否则 会出现构造函数递归
//Person gridFriend;
//Person friends[10];//数组也不行
Person* gridFriend = nullptr;
Person* friends[10] = { nullptr };
//如果不是自己类型的类 是可以声明非指针的
Pet pet = Pet();
Pet* pet2 = nullptr;
};
使用示例:
Person person;
person.name = "tao";
cout << person.name << endl; // 输出:tao
成员变量的使用和初始化
栈上创建
Person p; p.age = 10; cout << p.age << endl;//10 cout << p.name << endl;//韬老狮 cout << p.pos.x << endl;//4 cout << p.sex << endl;//0
堆上创建
Person* p2 = new Person(); cout << p2->age << endl; // 18
必须对成员变量进行初始化:
- 在声明时直接赋初值
- 在构造函数中初始化
如果我们不对成员变量进行初始化,那么他们的初始值会是一种不确定的状态。需避免此类情况。
总结
- 成员变量用于描述对象特征,声明在类内部,类型和数量不受限
- 必须初始化,且不能有非指针的本类类型成员
- 访问权限由
public
、private
、protected
决定 - 结构体、枚举和类的使用方式类似,均可在
.h
文件中声明与定义,使用时包含头文件即可
4.2 知识点代码
E_SexType.h
#pragma once
enum E_SexType
{
Man,
Woman,
};
Position.h
#pragma once
struct Position
{
int x;
int y;
Position(int x, int y) : x(x), y(y) {}
};
Pet.h
#pragma once
class Pet {};
Person.h
#pragma once
#include <iostream>
#include "Pet.h"
#include "Position.h"
#include "E_SexType.h"
using namespace std;
//类和枚举以及结构体 都可以独立的在.h头文件中进行声明和定义 要使用的时候 引用头文件即可
class Person
{
//成员变量
//1.用来描述 人 这种对象的特征
//2.写在类语句块中
//3.可以是任意的变量类型
//4.数量不限制
//5.是否赋值根据需求定 如果有构造函数可以在其中初始化 如果没有建议 都赋值一个初始值
public:
string name = "韬老狮";
int age = 18;
E_SexType sex = Man;
Position pos = Position(4,5);
private:
//6.不能有非指针类型的自己类型的成员 否则 会出现构造函数递归
//Person gridFriend;
//Person friends[10];//数组也不行
Person* gridFriend = nullptr;
Person* friends[10] = { nullptr };
//如果不是自己类型的类 是可以声明非指针的
Pet pet = Pet();
Pet* pet2 = nullptr;
};
Lesson04_面向对象_封装_成员变量和访问修饰符.cpp
#include <iostream>
#include "Person.h"
int main()
{
#pragma region 知识回顾 类和对象
// 声明类
// 类一般
// 在.h结尾的头文件中声明
// 在.cpp结尾的源文件中定义
// 对于小型类或者模板类,可以在头文件中直接完成声明和定义
//class 类名
//{
//访问修饰符:(可省略)
//构造函数、析构函数
//特征——成员变量
//行为——成员方法
//等等
//};
//声明 类对象
//步骤一:引用类头文件
//步骤二:声明对象
//普通对象(栈上)
//类名 变量名;
//类名 变量名 = 构造函数名(...);
//指针对象(堆上)
//类名* 变量名 = new 构造函数名(...);
//引用对象(根据引用对象自己决定在栈还是堆)
//类名& 变量名 = 想要引用的对象;
#pragma endregion
#pragma region 知识点一 成员变量
//基本规则
//1.声明在类语句块中
//2.用来描述对象的特征
//3.可以是任意变量类型
//4.数量不做限制
//5.是否赋值根据需求来定(老版本C++中不能直接在声明时赋值,只能在构造函数中赋值)
//6.不能有非指针类型的自己类型的成员
//没声明访问修饰符前类不能直接使用 会提示不可访问编译报错 结构体才可以
//Person person;
//person.name = "tao";
#pragma endregion
#pragma region 知识点二 访问修饰符
// 3P
// public —— 公共的 自己(内部)和别人(外部)都能访问和使用(完全公开,任何地方都能访问)
// private —— 私有的 自己(内部)才能访问和使用 不写 默认为private(严格私有,只有当前类内部才能访问)
// protected —— 保护的 自己(内部)和子类才能访问和使用(对自己和子类开放,外部不可访问)
// 决定类内部的成员 的 访问权限
//声明访问修饰符后类可以直接使用
Person person;
person.name = "tao";
cout << person.name << endl;//tao
#pragma endregion
#pragma region 知识点三 成员变量的使用和初始值
//栈上
Person p;
p.age = 10;
cout << p.age << endl;//10
cout << p.name << endl;//韬老狮
cout << p.pos.x << endl;//4
cout << p.sex << endl;//0
//堆
Person* p2 = new Person();
cout << p2->age << endl;//18
//一定要对类中的成员变量进行初始化
//1.在声明时 直接初始化
//2.在构造函数中初始化
//如果我们不对成员变量进行初始化
//那么他们的初始值会是一种不确定的状态
//我们一定要避免这种情况
//因此我们需要对他们进行初始化
#pragma endregion
//总结
//成员变量
//描述特征
//类中声明
//数量任意
//类型任意
//一定要初始化
//不能有非指针类型的自己类型的成员
//
//3p
//public 公共 内外
//private 私有 内
//protected 保护的 内和子类
//结构体、枚举可以在.h头文件中声明和定义
//要使用时和类一样 引用头文件即可
}
4.3 练习题
3P是什么?
public:公共的 内外
private:私有的 内
protected:保护的 内和子类
定义一个人类,有姓名,身高,年龄,家庭住址等特征 用人创建若干个对象
#pragma once
#include <iostream>
using namespace std;
class Person
{
public:
string name = "";
float height = 0;
int age = 0;
string homeAddress = "";
};
Person p;
p.name = "韬老狮";
p.age = 18;
p.height = 190;
p.homeAddress = "广州";
Person* p2 = new Person();
p2->name = "主席";
p2->height = 180;
p2->age = 16;
p2->homeAddress = "北京";
delete(p2);
p2 = nullptr;
定义一个学生类,有姓名,学号,年龄,同桌等特征。用学生类创建若干个学生
#pragma once
#include <iostream>
using namespace std;
class Student
{
public:
string name = "";
int num = 0;
int age = 0;
Student* deskmate = nullptr;
};
Student s;
s.name = "小明";
s.age = 6;
s.num = 1;
Student s2;
s2.name = "小红";
s2.age = 6;
s2.num = 1;
s.deskmate = &s2;
s2.deskmate = &s;
定义一个班级类,有专业名称,教室容量,学生等 创建一个班级对象
#pragma once
#include <iostream>
#include "Student.h"
using namespace std;
class Class
{
public:
string name = "";
int capacity = 30;
Student* students[30] = {nullptr};
};
Class* c = new Class();
c->name = "游戏开发";
c->capacity = 30;
c->students[0] = &s;
cout << c->students[0]->name << endl;
c->students[1] = &s2;
cout << c->students[1]->name << endl;
值类型赋值测试一
Person p;
p.age = 10;
Person p2;
p2.age = 20;
请问 p.age 为多少?
cout << person.age << endl; //10 互相独立没有任何关系
值类型赋值测试二
Person p;
p.age = 10;
Person p2 = p;
p2.age = 20;
请问 p.age 为多少?
//请问person.age为多少?
cout << person.age << endl; //10 不是new 在栈上是复制一份 改person2不会影响person
栈上值类型赋值测试
Student s;
s.age = 10;
int age = s.age;
age = 20;
请问 s.age 为多少?
cout << student.age << endl; //10 在栈上是复制一份
指针引用赋值测试
Student s;
s.deskmate = new Student();
s.deskmate.age = 10;
Student* s2 = s.deskmate;
s2.age = 20;
请问 s.deskmate.age 为多少?
cout << student.deskmate->age << endl; //20
//deskmate 是存的在堆上开辟的Student对象的地址
//student2赋值deskmate 存的也是地址
//指向的是同一个内存区域 修改对应内存上的值都会受到影响
4.4 练习题代码
StuClassdent.h
#pragma once
#include <iostream>
#include "Student.h"
using namespace std;
class Class
{
public:
string name = "";
int capacity = 30;
Student* students[30] = {nullptr};
};
Person.h
#pragma once
#include <iostream>
using namespace std;
class Person
{
public:
string name = "";
float height = 0;
int age = 0;
string homeAddress = "";
};
Student.h
#pragma once
#include <iostream>
using namespace std;
class Student
{
public:
string name = "";
int num = 0;
int age = 0;
Student* deskmate = nullptr;
};
Lesson04_练习题.cpp
#include <iostream>
#include "Person.h"
#include "Student.h"
#include "Class.h"
int main()
{
#pragma region 练习题一
//3P是什么?
//public:公共的 内外
//private:私有的 内
//protected:保护的 内和子类
#pragma endregion
#pragma region 练习题二
/*定义一个人类,有姓名,身高,年龄,家庭住址等特征
用人创建若干个对象*/
Person p;
p.name = "韬老狮";
p.age = 18;
p.height = 190;
p.homeAddress = "广州";
Person* p2 = new Person();
p2->name = "主席";
p2->height = 180;
p2->age = 16;
p2->homeAddress = "北京";
delete(p2);
p2 = nullptr;
#pragma endregion
#pragma region 练习题三
//定义一个学生类,有姓名,学号,年龄,同桌等特征。用学生类创建若干个学生
Student s;
s.name = "小明";
s.age = 6;
s.num = 1;
Student s2;
s2.name = "小红";
s2.age = 6;
s2.num = 1;
s.deskmate = &s2;
s2.deskmate = &s;
#pragma endregion
#pragma region 练习题四
//定义一个班级类,有专业名称,教室容量,学生等
//创建一个班级对象
Class* c = new Class();
c->name = "游戏开发";
c->capacity = 30;
c->students[0] = &s;
cout << c->students[0]->name << endl;
c->students[1] = &s2;
cout << c->students[1]->name << endl;
#pragma endregion
#pragma region 练习题五
//Person person;
//person.age = 10;
//Person person2;
//person2.age = 20;
////请问person.age为多少?
//cout << person.age << endl;//10 互相独立没有任何关系
#pragma endregion
#pragma region 练习题六
Person person;
person.age = 10;
Person person2 = person;
person2.age = 20;
//请问person.age为多少?
cout << person.age << endl;//10 不是new 在栈上是复制一份 改person2不会影响person
#pragma endregion
#pragma region 练习题七
//Student student;
//student.age = 10;
//int age = student.age;
//age = 20;
////请问student.age为多少?
//cout << student.age << endl;//10 在栈上是复制一份
#pragma endregion
#pragma region 练习题八
Student student;
student.deskmate = new Student();
student.deskmate->age = 10;
Student* student2 = student.deskmate;
student2->age = 20;
//请问student.deskmate->age为多少?
cout << student.deskmate->age << endl;//20
//deskmate 是存的在堆上开辟的Student对象的地址
//student2赋值deskmate 存的也是地址
//指向的是同一个内存区域 修改对应内存上的值都会受到影响
#pragma endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com