当前位置:首页 » 《关于电脑》 » 正文

【C++】类与对象(上篇)

10 人参与  2024年11月08日 08:42  分类 : 《关于电脑》  评论

点击全文阅读


?个人主页:小米里的大麦-CSDN博客

?所属专栏:C++_小米里的大麦的博客-CSDN博客

?代码托管:C++: 探索C++编程精髓,打造高效代码仓库 (gitee.com)

⚙️操作环境:Visual Studio 2022

目录

一、本节目标

二、面向过程和面向对象初步认识(过程与面向对象编程)

三、类的引入(Introduction to Classes)

四、类的定义(Defining a Class)

五、类的访问限定符及封装(Access Specifiers and Encapsulation)

六、类的作用域(Class Scope)

七、类的实例化(Instantiation of Classes)

八、类对象模型(Class Object Model)

结构体内存对齐规则(Struct Memory Alignment Rules)

九、this指针

1. 引出:什么是this指针?

2. 特性:

3.与C的对比:

4.常见易错点:

5.小结:

总结 

共勉


一、本节目标

面向过程和面向对象初步认识 类的引入 类的定义 类的访问限定符及封装类的作用域 类的实例化 类的对象大小的计算 类成员函数的this指针

二、面向过程和面向对象初步认识(过程与面向对象编程)

面向过程编程(ProceduralProgramming)

关注“过程”或“步骤”。将问题分解为函数,每个函数执行一个特定的任务。主要依赖函数调用,常见于C语言。
#include <stdio.h>// 面向过程编程: 通过函数处理数据void process(int data) {    printf("Processing data: %d\n", data);}int main() {    int data = 42;    process(data);    return 0;}

面向对象编程(Object-OrientedProgramming)

关注“对象”,将数据与操作数据的方法结合。通过对象之间的交互解决问题,常见于C++。
#include <iostream>using namespace std;class Processor {public:    void process(int data) {        cout << "Processing data: " << data << endl;    }};int main() {    Processor p;    p.process(42);    return 0;}
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

三、类的引入(Introduction to Classes)

C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;但在C++中,structclass可以包含变量函数

#include <iostream>#include <cstdlib> // for malloc and freeusing namespace std;typedef int DataType;struct Stack {    DataType* array;    size_t capacity;    size_t size;    // 初始化函数    void Init(size_t cap) {        array = (DataType*)malloc(sizeof(DataType) * cap);        if (!array) {            perror("malloc failed");            return;        }        capacity = cap;        size = 0;    }    // 压栈操作    void Push(const DataType& data) {        array[size++] = data; // 简化的例子,未考虑扩容    }    // 取栈顶元素    DataType Top() {        return array[size - 1];    }    // 销毁栈    void Destroy() {        if (array) {            free(array);            array = nullptr;        }    }};int main() {    Stack s;    s.Init(10);    s.Push(1);    s.Push(2);    cout << "Top element: " << s.Top() << endl;    s.Destroy();    return 0;}

上面结构体的定义,C++中更喜欢用class来代替。(【C++】class详解(与struct对比讲解)-CSDN博客)

四、类的定义(Defining a Class)

类的定义class是定义类的关键字。类是对象的蓝图,包含成员变量(属性)和成员函数(方法)。

类定义语法

class ClassName {    // 成员变量    // 成员函数};class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。

两种定义方式

在类体中定义成员函数:这样的函数可能被编译器视为inline内联函数。类声明与定义分离:通常将类的声明放在.h文件中,成员函数的定义放在.cpp文件中。注意:成员函数名前需要加类名::

示例1:类体中定义所有内容

#include <iostream>using namespace std;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, _month, _day;};int main() {    Date today;    today.Init(2024, 9, 22);    today.Print();    return 0;}

示例2:类声明与定义分离

// Date.hclass Date {public:    void Init(int year, int month, int day);    void Print();private:    int _year, _month, _day;};// Date.cpp#include <iostream>#include "Date.h"using namespace std;void Date::Init(int year, int month, int day) {    _year = year;    _month = month;    _day = day;}void Date::Print() {    cout << _year << "-" << _month << "-" << _day << endl;}int main() {    Date today;    today.Init(2024, 9, 22);    today.Print();    return 0;}

五、类的访问限定符及封装(Access Specifiers and Encapsulation)

访问限定符用于控制类的成员是否能够在类外部访问:

public:类外可以访问。private:类外部不能直接访问,只能通过类的内部方法操作。protected:类外部无法访问,但在继承中可以访问。

封装(Encapsulation):隐藏类的实现细节,仅对外提供公共接口,保证数据的安全性。

示例: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, _month, _day;  // 这些变量无法在类外直接访问};int main() {    Date today;    today.Init(2024, 9, 22);    today.Print();  // 只能通过Print()访问日期信息    return 0;}

六、类的作用域(Class Scope)

类的成员定义在类的作用域内,在类外部使用成员函数时,必须用域操作::指定该成员属于哪个作用类。

class Person {public:    void SetName(const char* name);    void PrintName();private:    char _name[20];};// 类外定义成员函数void Person::SetName(const char* name) {    strcpy(_name, name);  // 设置名字}void Person::PrintName() {    cout << "Name: " << _name << endl;  // 打印名字}int main() {    Person p;    p.SetName("Alice");    p.PrintName();    return 0;}

七、类的实例化(Instantiation of Classes)

类的实例化是指通过类的定义创建对象,分配实际的内存空间给成员变量。

class Car {public:    void SetBrand(const char* brand) {        strcpy(_brand, brand);    }    void Print() {        cout << "Car brand: " << _brand << endl;    }private:    char _brand[20];};int main() {    Car car1, car2;  // 实例化两个对象    car1.SetBrand("Toyota");    car2.SetBrand("Honda");    car1.Print();    car2.Print();    return 0;}

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

类就像谜语一样,对谜底来进行描述,谜底就是谜语的一个实例。

谜语:"年纪不大,胡子一把,主人来了,就喊妈妈" 谜底:山羊

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

int main(){     Person._age = 100;   // 编译失败:error C2059: 语法错误:“.”     return 0;}Person类是没有空间的,只有Person类实例化出的对象才有具体的年龄。

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

八、类对象模型(Class Object Model)

类对象的大小由成员变量的大小决定,成员函数的代码不会占用对象的存储空间。

空类的大小为1字节,确保每个对象都有唯一标识。
class Empty {};class A {private:    int _x;    char _y;};int main() {    cout << "Size of Empty class: " << sizeof(Empty) << endl;    cout << "Size of A: " << sizeof(A) << endl;  // 由于内存对齐的影响,可能比预期的更大    return 0;}

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

结构体内存对齐规则(Struct Memory Alignment Rules)

内容对齐的规则(【C语言】结构体内存布局解析——字节对齐_字节对齐规则-CSDN博客):

第一个成员从偏移量为0的位置开始。其他成员遵循它们大小的整数倍对齐。总大小为最大对齐数的整数倍。
#include <iostream>using namespace std;struct S1 {    char c;    int i;};struct S2 {    int i;    char c;};int main() {    cout << "Size of S1: " << sizeof(S1) << endl;  // 8字节,内存对齐使得char占4字节    cout << "Size of S2: " << sizeof(S2) << endl;  // 8字节    return 0;}

九、this指针

在C++中,this指针是一个特殊的指针,用于指向调用成员函数的当前对象(当前对象)。它只在类的非静态成员函数下面可用,是传递方式的。是对this指针隐式的详细讲解,包括特性、与C语言的对比,以及常见的易错点。

1. 引出:什么是this指针?

当一个对象调用其类的非静态成员函数时,编译器会自动传递该对象的地址给函数。this指针就是该对象的地址的成员函数。它可以用于在成员函数中调用该函数的对象的地址成员。

class MyClass {public:    int value;    void setValue(int value) {        this->value = value;  // 使用this指针,避免成员变量与参数重名冲突    }};在上面的例子中,this->value是指当前对象的成员变量value,而value(没有this)指的是函数参数。

2. 特性:

隐式传递this指针不需要显式声明,它在所有非静态成员函数中隐式可用。

常量性this指针是常量指针,无法修改其指向的对象。即this类型为MyClass* const

class MyClass {public:    void func() {        // this = nullptr; // 错误!无法修改this指针的指向    }};

指向当前对象this指向调用该成员函数的当前对象。

MyClass obj;obj.func();  // this指针指向obj

在常量成员函数中的this指针:在常量成员函数中,this指针是指向常量的指针,其类型为const MyClass* const,表示不能this修改对象的数据成员。

class MyClass {public:    void func() const {        // this->value = 10;  // 错误!无法修改常成员函数中的对象数据    }};

3.与C的对比:

C语言本身不支持类和对象的概念,因此也不存在this指针。在C中,要模拟类似的行为,通常需要显式传递结构体指针来访问结构体的成员。

C++中的this指针对应于在C语言中手动传递对象指针给函数的做法:// C语言模拟对象方法struct MyClass {    int value;};void setValue(struct MyClass* self, int value) {    self->value = value;}在C++中,这种显着式的传递结构指针的方式通过this指针抓取方式和自动化,简化了编程。

4.常见易错点:

修改this指针this是常量指针,不能修改其指向对象,错误的代码如下:

class MyClass {public:    void func() {        // this = nullptr;  // 错误,无法修改this指针的指向    }};

在静态成员函数中使用this:静态成员函数属于类本身,而不是某个特定对象,因此,静态成员函数中没有this指针。如果尝试在静态成员函数中使用this,会出现编译错误。

class MyClass {public:    static void staticFunc() {        // this->value = 10;  // 错误,静态成员函数没有this指针    }};

返回*this:在链式调用时,经常会返回当前对象的引用,返回*this是合法的用法。常见的用法如下:

class MyClass {public:    MyClass& setValue(int value) {        this->value = value;        return *this;  // 返回当前对象的引用,支持链式调用    }};

在构造函数或解析构造函数中使用this:在构造函数中使用this指针是安全的,但需要注意不要在构造函数中将this指针导出出去(比如在构造函数中调用虚函数)。在构造函数中,this指向即将被关注的对象,因此要小心避免对已关注的资源操作。

5.小结:

this指针用于指向当前对象,并在非静态成员函数中隐式传递。它是一个常量指针,不能修改指向的对象。静态成员函数中没有this指针。this在C++中简化了对象成员访问,而在C语言中,需要手动传递结构体指针。

掌握this指针有助于理解对象成员的访问方式和C++类的工作原理。

总结 

本文介绍了对象编程中的类、对象、封装、作用域、实例化、对象模型、内存定位和this指针的详细内容和代码示例。你可以通过编写这些代码加深理解,并尝试修改运行和他们来更好地掌握这些概念。

共勉


点击全文阅读


本文链接:http://zhangshiyu.com/post/183935.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1