【C++】类和对象——类的引入、类的访问限定符、类的作用域、类的实例化、类的储存、this指针的引出和特性

news/2024/12/21 20:43:42/

文章目录

  • 1.类的引入
  • 2.类的访问限定符
  • 3.类的作用域
  • 4.类的实例化
  • 5.类的储存
  • 6.this指针
    • 6.1this指针的引出
    • 6.2this指针的特性

1.类的引入

  C++是在C的基础上加以扩展。

  在C语言中,我们想要让一个类型含有多种成员变量,我们使用结构体;而在C++中我们可以使用类和结构体。可以说在一般情况下类要优于结构体:

(1)结构体和类都可以包含一组数据成员,这些成员可以是不同的数据类型和集合类型。

(2)结构体和类都可以包含一组成员函数,这些函数可以操作数据成员和执行其他任务。

(3)类比结构体更具有抽象和封装特性,类中的数据成员和成员函数可以通过访问控制符private、protected、public来控制外部访问和使用。

(4)结构体可以进行基本操作,如赋值、比较和作为函数参数传递等。类继承了结构体的这些基本操作。同时,也可实现更多的高级操作,并具有更好的可维护性、可扩展性和数据隐私性。

(5)在C++中,结构体可以看作是一种类,而类可以扮演结构体的角色。

  在C++中,类是面向对象编程的基础,它提供了许多方便的编程手段,包括封装、继承、多态和动态内存分配等,使得程序员能够更方便地开发大型、复杂的应用程序。因此,总体来说,相比结构体,类更加灵活、丰富和易用,并且有更多更复杂的应用场景。

用C++定义一个学生类:

#include <string>
using namespace std;// 定义学生类
class Student {string name;int age;double score;
};

2.类的访问限定符

  C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

  在C++中,类的成员可以使用三种不同的访问限定符来控制成员的可访问性,它们分别是:

(1)private(私有访问限定符):类的私有成员只能被类中的其他成员函数访问,不能被类外的任何函数或对象直接访问。

(2)protected(保护访问限定符):类的保护成员可以被类中的成员函数和派生类中的成员函数访问,但不能被类外的任何函数或对象直接访问。

(3)public(公共访问限定符):类的公共成员可以被类中的成员函数、派生类中的成员函数以及类外的任何函数或对象直接访问。

在这里插入图片描述

【访问限定符说明】

(1)public修饰的成员在类外可以直接被访问。

(2)protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)。

(3)访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。

(4)如果后面没有访问限定符,作用域就到 } 即类结束。

(5)class的默认访问权限为private,struct为public(因为struct要兼容C)。

注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

用C++定义一个学生类:

#include <string>
using namespace std;// 定义学生类
class Student {
private:string name;int age;double score;
public:Student(string n, int a, double s);  // 构造函数string get_name();void set_name(string n);int get_age();void set_age(int a);double get_score();void set_score(double s);void display();
};

3.类的作用域

  类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。

  C++中,类的作用域类似于命名空间。在C++中,类的作用域可以分为两个部分:

(1)类的定义部分:类的定义部分包括在类声明中的所有内容,例如成员变量、成员函数、访问限定符等。这些内容在类外不可见,在类内部可以直接访问,只有在类外使用类名限定符才能访问。

(2)类的成员函数定义部分:类的成员函数定义部分包括在类外定义的所有成员函数。在类声明中声明的成员函数只是一个函数声明,必须在类外部定义成员函数。在函数定义中,可以直接使用类名限定符访问类的成员变量和成员函数,例如className::memberName。


用C++定义一个学生类:

#include <string>
using namespace std;// 定义学生类
class Student {
private:string name;int age;double score;
public:Student(string n, int a, double s);  // 构造函数string get_name();void set_name(string n);int get_age();void set_age(int a);double get_score();void set_score(double s);void display();
};// 构造函数的定义
Student::Student(string n, int a, double s) {name = n;age = a;score = s;
}// 学生姓名访问函数
string Student::get_name() {return name;
}// 学生姓名设置函数
void Student::set_name(string n) {name = n;
}// 学生年龄访问函数
int Student::get_age() {return age;
}// 学生年龄设置函数
void Student::set_age(int a) {age = a;
}// 学生成绩访问函数
double Student::get_score() {return score;
}// 学生成绩设置函数
void Student::set_score(double s) {score = s;
}// 显示学生信息
void Student::display() {cout << "姓名:" << name << endl;cout << "年龄:" << age << endl;cout << "成绩:" << score << endl;
}

4.类的实例化

  用类类型创建对象的过程,称为类的实例化。

(1)类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;比如:入学时填写的学生信息表,表格就可以看成是一个类,来描述具体学生信息。

(2)一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

(3)类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间。
在这里插入图片描述


用C++定义一个学生类:

#include <string>
using namespace std;// 定义学生类
class Student {
private:string name;int age;double score;
public:Student(string n, int a, double s);  // 构造函数string get_name();void set_name(string n);int get_age();void set_age(int a);double get_score();void set_score(double s);void display();
};// 构造函数的定义
Student::Student(string n, int a, double s) {name = n;age = a;score = s;
}// 学生姓名访问函数
string Student::get_name() {return name;
}// 学生姓名设置函数
void Student::set_name(string n) {name = n;
}// 学生年龄访问函数
int Student::get_age() {return age;
}// 学生年龄设置函数
void Student::set_age(int a) {age = a;
}// 学生成绩访问函数
double Student::get_score() {return score;
}// 学生成绩设置函数
void Student::set_score(double s) {score = s;
}// 显示学生信息
void Student::display() {cout << "姓名:" << name << endl;cout << "年龄:" << age << endl;cout << "成绩:" << score << endl;
}// 主函数
int main() {// 实例化一个学生对象并设置其属性Student stu("Tom", 18, 90.5);// 显示学生信息stu.display();// 修改学生属性stu.set_name("Jack");stu.set_age(19);stu.set_score(88.5);// 再次显示学生信息stu.display();return 0;
}

5.类的储存

  C++ 中的类对象是存储在计算机内存中的,存储方式取决于具体的编译器、操作系统和硬件等因素。一般来说,类对象在内存中的存储是连续的,其中包括成员变量(也称为类数据成员)和成员函数(也称为类成员函数)。

  成员变量存储的位置会根据其访问修饰符的不同而分为公有、私有或保护成员。对于公有成员变量,可以通过对象或者指向对象的指针直接访问。而私有成员变量和保护成员变量只能由类内部的成员函数通过 this 指针来访问,其它方式都无法直接访问。

  成员函数存储的位置和成员变量不同:类的成员函数是在类外定义的,因此它们不会占用对象存储空间。不同的成员函数有不同的调用方式:对于普通成员函数,有固定的传参方式,会在函数内部调用 this 指针指向的对象;而静态成员函数则不需要通过对象调用,因此没有 this 指针,并且可以被所有对象和类共享。

  需要注意的是,在类中定义的静态成员变量在内存中只有一份,不属于对象而是属于类本身。所以,无论有多少个类的对象都只会有一个静态成员变量存储空间。

  总的来说,类存储方式是由编译器、操作系统和硬件等多种因素共同决定的,并且不同编译器和平台的存储方式可能存在差异。但是,我们可以通过了解类的访问修饰符和成员函数等基本特性,来更好地理解类在内存中的存储原理以及如何使用和管理类对象的内存。

在这里插入图片描述

结构体内存对齐规则

// 类中既有成员变量,又有成员函数
class A1 {
public:void f1(){}
private:int _a;
};
// 类中仅有成员函数
class A2 {
public:void f2() {}
};
// 类中什么都没有---空类
class A3
{};sizeof(A1) : ___4___  sizeof(A2) : ___1___  sizeof(A3) : ___1___

   结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐;注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。

6.this指针

6.1this指针的引出

先定义一个日期类:

class Date
{ 
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout <<_year<< "-" <<_month << "-"<< _day <<endl;}private:int _year; // 年int _month; // 月int _day; // 日int a;
};int main()
{Date d1, d2;d1.Init(2022,1,11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}

对于上述类,有这样的一个问题:

Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

6.2this指针的特性

  在 C++ 中,this 是一个指向当前对象的指针,它有以下特性:

(1)this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。

(2)只能在“成员函数”的内部使用。

(3)this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。

(4)this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
在这里插入图片描述

1.this指针可以为空吗?
  this指针是可以为空指针的,但是不能解引用。通常我们不应该让this指针为空指针。

2.this指针存在哪里?

   this指针存放在调用函数的栈帧里面,VS下对this指针进行了优化,存放在寄存器ECX里面。

  需要注意的是,this 指针是常量指针,它指向的地址不能被修改。因此,在成员函数中不能直接修改 this 指针的指向,否则会导致编译错误。另外,在一些特殊场合下,this 指针的值可能会被修改(如使用 const_cast 显式地转换掉 const 属性),但这样做通常是不被推荐的,因为会破坏对象的封装性和安全性。

这些就是C++中类和对象的简单介绍了😉
如有错误❌望指正,最后祝大家学习进步✊天天开心✨🎉


http://www.ppmy.cn/news/91074.html

相关文章

项目管理自动化 工作效率顶呱呱

项目管理&#xff0c;是职场人进阶发展的必备高阶能力&#xff0c;需要在复杂的环境中有效整合资源、高效助力团队实现整体的项目目标。 一个好的项目管理者&#xff0c;需要合理规划项目进展&#xff0c;实时同步需求、及时沟通进展&#xff0c;合理判断项目风险&预警&am…

操作系统第五章——输入输出管理(中)

提示&#xff1a;若我会见到你&#xff0c;事隔经年&#xff0c;我如何向你招呼&#xff0c;以眼泪&#xff0c;以沉默 文章目录 5.2.1 IO核心子系统知识总览功能要在那个层次实现 5.2.2 假脱机技术&#xff08;SPOOLing&#xff09;知识总览什么是脱机技术假脱机技术——输入井…

还是畅通工程(Kruscal)_02

#include<bits/stdc.h> using namespace std; const int MAXN1000; int father[MAXN];//父亲结点 int height[MAXN];//高度结点 struct Edge{int from;int to;int length; }; Edge edge[MAXN*MAXN]; //初始化 void init(int n){for(int i0;i<n;i){father[i]i;height[…

PMP例题 学习记录

1、 项目经理同时担任项目A和项目B的管理工作&#xff0c;其中项目A是符合公司总体战略计划的项目&#xff0c;项目B是项目经理直接领导负责的项目&#xff0c;两个项目在资源使用需求上有冲突&#xff0c;项目经理应该怎么办&#xff1f; A、请求PMO对两个项目的优先级进行排…

震惊!吊打面试官,必备的 SpringCloud 微服务面试题(VIP典藏版)

目录 福利&#xff1a;文末有分享SpringBoot教程及源码哦《【imooc-java2021】体系课-Java工程师 》 Spring Cloud微服务面试题 1、Spring Cloud Netflix和Spring Cloud Alibaba包括哪些组件 2、Nacos是CP还是AP? 3、Nacos作为注册中心应该选择是CP还是AP&#xff1f; 4、…

油猴脚本尝试

现在是这样的&#xff0c;我这边有个运维系统&#xff0c;里面有个日志&#xff0c;我们经常要复制&#xff0c;然后我们复制的时候需要打开内容&#xff0c;然后去选中复制。 类似于这种&#xff0c;我觉得这个时候&#xff0c;去选中复制就很麻烦&#xff0c;右边这里不是有…

Android之 MVC到MVVM架构发展和封装

一 简介 1.1 软件架构发展趋势是解耦&#xff0c;即分离数据层和视图层&#xff0c;使得数据层专注于业务的数据和逻辑处理。从而提高代码的可读可编辑效率&#xff0c;提高团队协作能力&#xff0c;项目的生产能力&#xff0c;降低后期维护成本。 1.2 Android架构发展MVC -…

【Java递归】一篇文章带你了解,什么是递归 ,递归的特点,递归应用场景,递归练习题

博主&#xff1a;東方幻想郷 专栏分类&#xff1a;Java | 从入门到入坟 Java递归 ⭐ 递归的定义⭐ 递归的特点⭐ 递归应用场景⭐ 简单例子⭐ 递归练习题&#x1f30c; 练习题模板&#x1f3f4;‍☠️ 练习题答案&#xff1a; ⭐ 递归的定义 &#x1f31f;递归是一种在方法通过调…