前言
类与对象(一)
文章目录
- 一、面向对象和面向过程的对比
- 二、类的引入
- 2.1 C++中的结构体
- 2.2 类
- 2.3 类定义方法
- 2.4 修饰限定符
- 2.5 封装
- 2.6 类的实例化
- 2.7 类对象的大小
- 三、this指针
- 3.1 this 指针的使用
一、面向对象和面向过程的对比
面向过程编程是将程序看作一系列的步骤或过程,然后逐步完成各个步骤,从而实现一个程序的方法。而面向对象编程是将问题分解为对象,每个对象包含数据(属性)和操作数据的方法(方法)。
以将大象装进冰箱为例:
面向对象编程(OOP):
- 大象对象: 有属性(大小、重量)和方法(进入冰箱)。
- 冰箱对象: 有属性(容量、门的状态)和方法(打开门)。
面向过程编程:
- 过程: 分解为步骤。打开冰箱的门,把大象放进去,关闭门。
我们知道面向过程的编程语言有C语言,现在我们来认识一下面向对象编程的编程语言的代表之一——C++。
二、类的引入
2.1 C++中的结构体
在C语言中我们可以使用struct
(结构体)来自定义类型,同样在C++也有结构体的使用,但有所不同:
C++中的struct
的特点:
-
默认访问修饰符: 在C++中,
struct
的成员默认是公有的(public,访问限定修饰符),与C语言中相同。 -
支持成员函数: 与C不同,C++中的
struct
可以包含成员函数。// 在C++中的struct示例 struct Person {// 成员变量char name[50];int age;// 成员函数void displayInfo() {cout << "Name: " << name << "\nAge: " << age << endl;} };
-
继承和访问控制: C++中的
struct
也可以继承其他结构体或类,并且支持访问控制,包括私有、保护和公有继承。// 基类 class Animal { public:void eat() {cout << "动物在吃东西。" << endl;} };// 派生类 struct Dog : public Animal { // 公有继承void bark() {cout << "狗在叫" << endl;} };
C++中,struct
可以更多地用于实现类似于类的结构。
2.2 类
初始版本的 C++ 在设计时候的一个目标是与 C 语言保持高度的兼容性,以便现有的 C 代码可以逐渐迁移到 C++ 中。因此保留了struct,并稍微扩展了其功能,可以包含函数,增加修饰限定符等。但struct的访问权限是默认是公有的,因此,C++中引入了类的概念。
C++中,类是一种用户自定义的数据类型,在语法上与struct
非常相像。
类的基本结构包括成员变量(类的属性) 和 成员函数(类的方法):
//class为关键字 Time为类名
class Time {
public:int hours; //小时int minutes; //分int seconds; //秒
private:// 设置时间void setTime(int h, int m, int s);// 显示时间void displayTime();
};
2.3 类定义方法
有两种主要的类定义方式:定义在类外部的方式和定义在类内部的方式。
1. 定义在类外部的方式:
类的声明通常放在头文件(.h 文件)中,而类的定义则放在源文件(.cpp 文件)中。注意:成员函数定义时名字前需要加类名::,例如 int MyClass::getVar() const
示例:
// MyClass.h
#pragma onceclass MyClass {
private:int myVar;public:MyClass(); // 声明构造函数void setVar(int value); // 声明成员函数int getVar() const; // 声明成员函数
};// MyClass.cpp
#include "MyClass.h"MyClass::MyClass() {myVar = 0;
}void MyClass::setVar(int value) {myVar = value;
}int MyClass::getVar() const {return myVar;
}
2. 定义在类内部的方式:
类的声明和定义都放在类的内部。
示例:
// MyClass.h
#pragma onceclass MyClass {
private:int myVar;public:MyClass() {myVar = 0;}void setVar(int value) {myVar = value;}int getVar() const {return myVar;}
};
2.4 修饰限定符
在C++中,修饰限定符用于控制类中成员的访问权限。C++有三个主要的修饰限定符:public
、protected
和private
。
- public: 成员被声明为公有,可以在类的外部和内部访问。
- protected: 成员被声明为受保护的,可以在类的内部和派生类中访问,但在类的外部不能直接访问。
- private: 成员被声明为私有,只能在类的内部访问,不能在类的外部或派生类中直接访问。
修饰限定符通常出现在类的定义中,用于指定类成员的访问权限。以下是一个简单的示例:
class MyClass {
public:// 公有成员int publicVar;// 公有成员函数void publicFunction() {// 可以访问公有、受保护、私有成员publicVar = 1;protectedVar = 2;privateVar = 3;}protected:// 受保护成员int protectedVar;private:// 私有成员int privateVar;
};
在上面的示例中,publicVar
是公有成员,可以在类的外部直接访问。protectedVar
是受保护成员,只能在类的内部和派生类中访问。privateVar
是私有成员,只能在类的内部访问。
需要注意的是:class的默认访问权限为private,struct为public(因为struct要兼容C,这也是为什么要引入类的原因)
2.5 封装
封装是面向对象编程(OOP)的一个核心概念,它指的是将数据和操作数据的方法封装在一个单一的实体(类)中,并对外部隐藏对象的内部实现细节。封装通过将数据成员私有化,并提供公有的成员函数来实现,使得外部代码无法直接访问对象的内部数据,而是通过类的接口进行交互。
封装的主要目的有以下几点:
-
隐藏实现细节: 封装允许将实现细节隐藏在类的内部,使得外部代码无法直接了解或修改类的内部数据结构和实现。
-
简化接口: 封装通过提供公有的接口(成员函数)来与对象进行交互,使得外部代码只需关心如何使用对象,而不需关心对象的内部工作方式。
-
提高代码的模块性: 封装将对象的实现细节封装在一个单一的单元中,使得代码模块化,易于维护和重用。
简单点说,封装就像是你有一辆车,但你不需要知道引擎是怎么工作的,也不需要了解车轮是如何旋转的。你只需要知道一些关于这辆车的基本信息,比如怎么加速、怎么刹车,这就是车的接口。引擎和其他细节都被封装在车的内部,对你来说是不可见的。
2.6 类的实例化
类就像建筑设计图,对象是按照设计图实际要建造的房子。而实例化就像是在建造房子的过程。
举例:
#include <iostream>
using namespace std;// 定义一个简单的类
class Car {
public:// 成员变量string brand;int year;// 构造函数Car(string b, int y) : brand(b), year(y) {}// 成员函数void displayInfo() {cout << "Brand: " << brand << ", Year: " << year << endl;}
};int main() {// 声明并实例化 Car 类的对象Car myCar("Toyota", 2022);// 使用对象的成员函数myCar.displayInfo();return 0;
}
2.7 类对象的大小
类的大小由其成员变量的大小总和决定,不包括成员函数的大小。成员函数在每个对象中共享相同的代码,因此它们不会增加对象的大小。
成员变量的大小由它们的类型和数量决定。每个基本数据类型(如int、double等)在内存中占用的空间是确定的,而类类型的大小取决于其成员变量的大小。
考虑一个简单的示例:
class MyClass {
public:int integerVar;double doubleVar;char charVar;void func1();void func2();
};int main() {MyClass c1;cout << "c1的大小为" << sizeof(c1) << endl;return 0;
}
那么MyClass
类的对象大小将是24字节,当然这是在默认对齐数为8时的大小。
对象的大小也受到内存对齐的影响,可以参考这篇博文【C语言】自定义类型:结构体。
三、this指针
this
指针是一个特殊的指针,它指向当前对象的地址。
this
指针并不是一个明确存在于内存中的变量,而是编译器在代码生成阶段处理的一种机制,用于传递当前对象的地址给成员函数。
this
指针的存在是因为成员函数需要知道它们是在哪个对象上调用的,以便正确地访问该对象的成员变量和成员函数。
当你在类的成员函数中使用成员变量或调用成员函数时,编译器会隐式地将 this
指针传递给该函数,使得函数内部可以通过 this
指针来引用当前对象。
3.1 this 指针的使用
在类的成员函数中,可以使用 this 指针来引用当前对象的成员变量和成员函数。它允许在成员函数中访问当前对象的成员,即使成员的名称与参数名称相同也能够正确引用。
在传参及接收参数时不能显式地标出this。
class MyClass {
private:int _x;public:void setX(int x) {this->_x = x; // 使用this指针引用成员变量//在 C++ 中,如果成员函数中使用的变量名与成员变量名相同,编译器会默认使用成员变量,这是一种默认约定// _x = x; //或者直接使用成员变量名_x}int getX() const {return this->_x; // 使用this指针引用成员变量//return _x;}
};int main() {MyClass obj;obj.setX(42); // 必须隐式地传递this指针给setX函数,即在实参不标出this,也不在形参标出int value = obj.getX(); // 隐式地传递this指针给getX函数cout << "value=" << value << endl;
}
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。