C++ 类与对象Oop

这篇具有很好参考价值的文章主要介绍了C++ 类与对象Oop。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

同Java一样,C++具备这面向对象的概念。我们也可以和java对比着学习,发现他们的不同:
此处是我的java博客的链接:
我在VScode学Java类与对象(Java的类与对象、this关键字)

先了解下面的概念

过程性编程(Procedural programming)是一种编程范式,它将程序分解为一系列的步骤或过程。这些过程按照顺序执行,通常涉及函数和指令的调用。过程性编程强调程序的执行过程,以及数据和功能之间的分离。

面向对象编程(Object-oriented programming)是另一种编程范式,它将数据和功能组合成对象。对象可以包含数据(称为属性或成员变量)和操作数据的方法(称为方法或成员函数)。面向对象编程强调数据和功能的封装,继承和多态性。

一、类:用户定义的数据类型,用于封装数据和方法

类是一种用户定义的数据类型,用于封装数据和方法。
它可以包含成员变量(数据)和成员函数(方法),并且可以通过实例化创建对象。
提供了一种组织和管理代码的方式,以及实现数据抽象和封装的能力。

在面向对象编程中,类的定义通常包括类声明和类方法定义两部分。

类声明描述了类的数据部分,通常以数据成员的方式描述。同时,它也描述了类的公有接口,即类的方法或成员函数。这部分提供了类的蓝图,定义了类的结构和公有接口。

类方法定义描述了如何实现类的成员函数,即方法的具体实现细节。这部分提供了类成员函数的具体实现,包括方法的功能和操作。

#include <iostream>

using namespace std;

// Class declaration
class MyClass {
private:
    int data; // Data member

public:
    void setData(int value); // Member function declaration
    int getData(); // Member function declaration
};

// Class method definition
void MyClass::setData(int value) {
    data = value;
}

int MyClass::getData() {
    return data;
}

int main() {
    MyClass obj;
    obj.setData(42);
    cout << "Data: " << obj.getData() << endl;
    return 0;
}

1.1 对比结构体

C++中的结构体(struct)和类(class)都可以用来定义自定义数据类型。它们的主要区别在于默认的访问权限和成员函数。结构体的默认访问权限是公共的(public),而类的默认访问权限是私有的(private)。
此外,类可以包含成员函数和构造函数,而结构体不能包含成员函数,但可以包含构造函数。在实际使用中,结构体通常用于简单的数据聚合,而类用于更复杂的数据抽象和封装。

结构体示例
// 结构体示例
#include <iostream>
using namespace std;

struct Person {
    string name;
    int age=123;
};

int main() {
    Person person1;
    person1.name = "Alice";
    person1.age = 25;

    cout << "Name: " << person1.name << ", Age: " << person1.age << endl;

    return 0;
}
类示例

#include <iostream>
using namespace std;

class Person {
public:
    string name;
    int age;
    float score;
};

int main() {
    Person person1;
    person1.name = "Bob";
    person1.age = 30;
    person1.score = 89.5;
    cout << "Name: " << person1.name << ", Age: " << person1.age <<"score" <<person1.score<<endl;

    return 0;
}

警告–>主要目的:初始化

Clang-Tidy 提示 “Constructor does not initialize these fields: age” 是因为在代码中没有显式地在构造函数中初始化类的成员变量 age。而对于 name,因为它是一个 std::string 类型的成员变量,它有一个默认的构造函数,因此即使没有显式初始化,它也会被默认初始化为空字符串。

所以写成:

class Person {
public:
    string name;
    int age{};
    float score{};
};

1.2 定义类的过程并定义一个对象

1.2.1 定义类

class MyClass {
    // class members and methods go here
};

定义一个类的过程就是使用关键字class后面跟着类名,然后在大括号内定义类的成员变量和方法。明确我们需要的成员属性,在给定我们需要方法使得类更佳完整。

例子
class Cube {
private:
    int L, W, H;
public:
//    setter 和 getter
    void setL(int l) {
        L = l;
    }

    int getL() const {
        return L;
    }

    void setW(int w) {
        W = w;
    }

    int getW() const {
        return W;
    }

    void setH(int h) {
        H = h;
    }

    int getH() const {
        return H;
    }

//    表面积
    int area() const {
        return 2 * (L * W + L * H + W * H);
    }

//    体积
    int volume() const {
        return L * W * H;
    }
}

1.2.2 定义一个对象

//    在C++中
Cube c{};

// 使用大括号初始化语法对对象进行值初始化。这确保了对象的所有成员变量都被初始化为其默认值,
// 即int类型的成员变量会被初始化为0。
// 这种初始化方式在C++11标准中引入,它提供了更加一致和可靠的初始化语法,尤其是在涉及到类类型的初始化时。

//    在C++中,使用*操作符可以用来解引用指针。在你提供的代码中,
 Cube cube = *new Cube();

// 在C++中,使用*操作符可以用来解引用指针。在你提供的代码中,
// *new Cube()创建了一个新的Cube对象,并返回指向该对象的指针。
// 然后,*操作符被用来解引用这个指针,以便将指针指向的对象赋值给cube变量。
//简而言之,new Cube()创建了一个新的Cube对象,并操作符用来解引用指针,以便将指针指向的对象赋值给cube变量。

1.2.3 注意事项+例子

在C++中定义类时需要注意以下几点:

  1. 类的成员默认是私有的,需要使用public、protected或者private关键字来指定访问权限。
  2. 类的成员函数可以在类内部定义,也可以在类外部定义。
  3. 类的成员变量和方法可以通过对象的实例来访问。
// 2023/11/13日创建
#include <iostream>

using namespace std;

//PointClass
class Point {
private:
    // x,y坐标
    int X;
    int Y;
public:
    void setX(int x) { // 设置X坐标
        X = x;
    }

    int getX() { // 获取X坐标
        return X;
    }

    void setY(int y) { // 设置Y坐标
        Y = y;
    }

    int getY() { // 获取Y坐标
        return Y;
    }
};

//CircleClass
class Circle {
private:
    int C_R; // 圆的半径
    Point C_Center; // 圆心坐标
public:
    void setC_R(int r) { // 设置圆的半径
        C_R = r;
    }

    int getC_R() { // 获取圆的半径
        return C_R;
    }

    void setC_Center(Point p) { // 设置圆心坐标
        C_Center = p;
    }

    Point getC_Center() { // 获取圆心坐标
        return C_Center;
    }

    bool isPointInside(Point p) { // 判断点是否在圆内部
        int dx = p.getX() - C_Center.getX();
        int dy = p.getY() - C_Center.getY();
        int distanceSquared = dx * dx + dy * dy;
        int radiusSquared = C_R * C_R;
        return distanceSquared <= radiusSquared;
    }
};

int main() {
    // 创建Point对象
    Point p;
    p.setX(3); // 设置X坐标为3
    p.setY(4); // 设置Y坐标为4
    cout << "Point坐标: (" << p.getX() << ", " << p.getY() << ")" << endl;

    // 创建Circle对象
    Circle c;
    c.setC_R(5); // 设置圆的半径为5
    c.setC_Center(p); // 设置圆心坐标为Point对象p
    cout << "Circle半径: " << c.getC_R() << endl;
    cout << "Circle圆心坐标: (" << c.getC_Center().getX() << ", " << c.getC_Center().getY() << ")" << endl;

    // 判断点是否在圆内部
    Point testPoint;
    testPoint.setX(2);
    testPoint.setY(3);
    if (c.isPointInside(testPoint)) {
        cout << "点在圆内部" << endl;
    } else {
        cout << "点不在圆内部" << endl;
    }

    return 0;
}

C++ 类与对象Oop,L.的C++学习之路,c++,开发语言

1.2.4 分成头文件和源文件的方式

(0)注意事项

#ifndef和#define是C/C++中的预处理指令,用于防止头文件被多次包含。

#ifndef <标识>
#define <标识>
...
#endif

当头文件被包含到多个源文件中时,防止多次定义同一个标识符。如果标识符已经被定义过,则#ifndef和#define之间的代码会被忽略,直到#endif。

这样可以避免由于重复包含头文件而导致的重复定义错误。

(1)Point.h
// Point.h
#ifndef POINT_H
#define POINT_H

class Point {
private:
    int X;
    int Y;
public:
    void setX(int x);
    int getX();
    void setY(int y);
    int getY();
};

#endif
(2) Point.cpp
// Point.cpp
#include "Point.h"

void Point::setX(int x) {
    X = x;
}

int Point::getX() {
    return X;
}

void Point::setY(int y) {
    Y = y;
}

int Point::getY() {
    return Y;
}
(3) Circle.h
// Circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include "Point.h"

class Circle {
private:
    int C_R;
    Point C_Center;
public:
    void setC_R(int r);
    int getC_R();
    void setC_Center(Point p);
    Point getC_Center();
    bool isPointInside(Point p);
};

#endif
(4) Circle.cpp
// Circle.cpp
#include "Circle.h"

void Circle::setC_R(int r) {
    C_R = r;
}

int Circle::getC_R() {
    return C_R;
}

void Circle::setC_Center(Point p) {
    C_Center = p;
}

Point Circle::getC_Center() {
    return C_Center;
}

bool Circle::isPointInside(Point p) {
    int dx = p.getX() - C_Center.getX();
    int dy = p.getY() - C_Center.getY();
    int distanceSquared = dx * dx + dy * dy;
    int radiusSquared = C_R * C_R;
    return distanceSquared <= radiusSquared;
}
(5)main.cpp
// main.cpp
#include <iostream>
#include "Point.h"
#include "Circle.h"

using namespace std;

int main() {
    Point p;
    p.setX(3);
    p.setY(4);
    cout << "Point coordinates: (" << p.getX() << ", " << p.getY() << ")" << endl;

    Circle c;
    c.setC_R(5);
    c.setC_Center(p);
    cout << "Circle radius: " << c.getC_R() << endl;
    cout << "Circle center coordinates: (" << c.getC_Center().getX() << ", " << c.getC_Center().getY() << ")" << endl;

    Point testPoint;
    testPoint.setX(2);
    testPoint.setY(3);
    if (c.isPointInside(testPoint)) {
        cout << "Point is inside the circle" << endl;
    } else {
        cout << "Point is not inside the circle" << endl;
    }

    return 0;
}

1.3 构造函数和析构函数

对象的初始化和清除是C++中两个非常重要的操作,它们分别对应于构造函数和析构函数。

构造函数:主要作用是在创建对象是为对象的成员赋值,构造函数由编辑器自动调用,无需手动调用

构造函数用于对象的初始化,主要作用是在创建对象时为对象的成员赋值。构造函数的名称与类名相同,没有返回类型,可以有参数。当对象被创建时,构造函数会自动调用,无需手动调用。

析构函数:主要作用是在于对象销毁前系统自动调用,执行一些清除工作

析构函数用于对象的清理,主要作用是在对象销毁前执行一些清除工作,如释放动态分配的内存、关闭文件等。析构函数的名称是在类名前加上波浪号(~),没有返回类型,不接受任何参数。当对象被销毁时(例如超出作用域、delete操作符被调用),析构函数会自动调用,无需手动调用。

如果我们自己不提供构造函数或析构函数,编译器会自动生成默认的构造函数和析构函数,这些默认的函数会执行空实现。但是在某些情况下,我们可能需要自定义构造函数和析构函数来完成特定的初始化和清理工作。

1.3.1 构造函数: 类名(){}

构造函数的特点包括:

  1. 没有返回值也不写void。
  2. 构造函数的名称与类名相同。
  3. 构造函数可以有参数,因此可以发生重载。
  4. 程序在创建对象时会自动调用构造函数,无需手动调用,且只会调用一次。

1.3.2 析构函数: ~类名(){}

析构函数的特点包括:

  1. 析构函数的名称是在类名前加上波浪号(),例如ClassName。
  2. 析构函数没有返回类型,也不接受任何参数。
  3. 析构函数在对象被销毁时自动调用,用于执行对象的清理工作,如释放资源、关闭文件等。
  4. 如果用户没有显式定义析构函数,编译器会提供一个默认的空实现的析构函数。
  5. 如果类中有动态分配的资源(如使用new关键字分配的内存),通常需要在析构函数中释放这些资源,以避免内存泄漏。
  6. 每个类只能有一个析构函数,析构函数不可以有参数,因此不可以发生重载

1.3.3 示例

class Person {
public:
//    1.构造函数
/*没有返回值也不写void、和类名相同、可以有参数,因此可以发生重载*/
    Person() {
        cout << "Person()空参构造的调用" << endl;
    }
//     2. 析构函数:主要作用是在于对象销毁前系统自动调用,执行一些清除工作
/* 没有返回值也不写void、函数名称与类名相同,在名称前加上符号~、不可以有参数,因此不可以发生重载*/
    ~Person() {
        cout << "~Person()析构构造的调用" << endl;

    }

};

//构造和析构都是必须实现的,如果不成,编译器会给一个空实现
void test() {
    Person p;
/*栈上的数据,test执行完毕后,释放该对象*/
}

int main() {
// 公共作用域下
// 2.构造函数用外部函数调用
    test();
//或者这样的内部直接用方式
//Person();


//如果写在main函数中,那么main函数执行完毕,对象就释放了
    Person s;
    system("pause");


}

C++ 类与对象Oop,L.的C++学习之路,c++,开发语言

//构造和析构都是必须实现的,如果不成,编译器会给一个空实现
void test() {
    Person p;
/*栈上的数据,test执行完毕后,释放该对象*/
}
(1)这两种方式都可以创建Person对象,但它们的作用域和生命周期是不同的。
  1. test();:在test函数中创建了一个Person对象。这个对象是test函数的局部变量,所以它的作用域仅限于test函数。当test函数执行完毕后,这个对象就会被销毁,触发析构函数。

  2. Person();:这是一个匿名对象,它在创建后会立即被销毁。因为它没有名称,所以不能在后续的代码中引用它。这种方式通常用于临时对象的创建,或者作为函数参数。

这两种方式都可以创建对象,但是根据你的需求和对象的使用方式,你可能会选择其中一种。例如,如果你需要在函数中使用一个对象,然后在函数结束时自动销毁它,你可以在函数中创建对象。如果你只需要一个临时对象,你可以创建一个匿名对象。

(2)匿名对象

Person();:这行代码创建了一个匿名对象。这个匿名对象在创建后会立即被销毁,因为它没有名称,所以不能在后续的代码中引用它。这就是匿名对象的生命周期。

Person p =Person();:这行代码首先创建了一个匿名对象,然后通过拷贝构造函数将这个匿名对象的内容复制给了p对象,然后匿名对象被销毁。这样,p对象就拥有了匿名对象的数据,而且p对象的生命周期会持续到它离开其作用域。

这两种方式都可以创建对象,但是根据你的需求和对象的使用方式,你可能会选择其中一种。例如,如果你只需要一个临时对象,你可以创建一个匿名对象。如果你需要一个持久的对象,你可以创建一个具名对象。文章来源地址https://www.toymoban.com/news/detail-820246.html

到了这里,关于C++ 类与对象Oop的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • [C++] 类与对象(上)

    [C++] 类与对象(上)

      目录 1、前言 2、类的引入 3、类的定义 3.1 类的两种定义方式 4、类的访问限定符 5、类的作用域 6、类的实例化 7、类对象模型 7.1 内存对齐规则 7.1 类对象的存储方式 8、this指针 8.1 this指针的特性 8.2 this指针是否可以为空 C语言是 面向过程 的, 关注 的是 过程 ,分析出求解

    2024年02月15日
    浏览(8)
  • C++ 类与对象(下)

    C++ 类与对象(下)

    目录 1. 再谈构造函数 1.1 构造函数体赋值  1.2 初始化列表  1.3 explicit  2. static成员 2.1 概念 2.2 特性  3.友元 3.1友元函数   3.2 友元类 4. 内部类 5.匿名对象  6.拷贝对象时的一些编译器优化  7. 再次理解类和对象 1. 再谈构造函数 2. Static成员 3. 友元 4. 内部类 5.匿名对象

    2024年02月19日
    浏览(7)
  • C++ 类与对象(上)

    C++ 类与对象(上)

    目录 本节目标  1.面向过程和面向对象初步认识  2.类的引入  3.类的定义 4.类的访问限定符及封装 4.1 访问限定符 4.2 封装 5. 类的作用域 6. 类的实例化  7.类对象模型 7.1 如何计算类对象的大小 7.2 类对象的存储方式猜测 7.3 结构体内存对齐规则  8.this指针 8.1 this指针的引出

    2024年02月19日
    浏览(5)
  • 【C++】类与对象(中)

    【C++】类与对象(中)

    目录 1. 类的6个默认成员函数 2. 构造函数 2.1 概念 2.2 特性 3. 析构函数 3.1 概念 3.2 特性 4. 拷贝构造函数 4.1 概念 4.2 特征 5. 赋值运算符重载 5.1 运算符重载 5.2 赋值运算符重载 5.3 前置++和后置++重载 6. const成员 7. 取地址及const取地址操作符重载 如果一个类中什么成员都没有,

    2024年02月05日
    浏览(7)
  • 【C++】类与对象(下)

    【C++】类与对象(下)

      若想了解什么是类、封装的意义可以移步  【C++】类与对象(引入)   若对六大成员函数或const成员函数有疑问的这篇文章可能可以帮到你  【C++】类与对象(上) 目录 系列文章 前言 1.初始化列表 1.1概念 1.2特性  1.2.1必须使用初始化列表的情况 1.2.2初始化的顺序 2.expli

    2023年04月14日
    浏览(10)
  • c++类与对象

    c++类与对象

    🐶博主主页: @ᰔᩚ. 一怀明月ꦿ  ❤️‍🔥 专栏系列: 线性代数,C初学者入门训练,题解C,C的使用文章 🔥 座右铭: “不要等到什么都没有了,才下定决心去做” 🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀  目录 🐰类与对象 🌸

    2023年04月08日
    浏览(9)
  • C++类与对象(下)

    您好这里是limou3434的博文,感兴趣可以看看我的其他博文系列。 这一部分是对C++类的一些补充:初始化列表、友元、内部类。 在给对象进行初始化的时候,如果选择函数体内进行初始化是一件很麻烦的事情。 但是这样写是没有办法过的,要成功运行的话只能写一个默认构造

    2024年02月11日
    浏览(10)
  • 【C++】类与对象(上)

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

    之前的文章中讲解了,什么是类、类的实例化,以及封装的意义,若仍有不理解的部分可以移步上一篇文章  【C++】类与对象(引入) 目录 系列文章 1.默认成员函数 2.构造函数 2.1定义 2.2特性 2.2.1重载构造函数 2.2.2与缺省参数混合使用 2.2.3默认构造函数 3.析构函数 3.1定义

    2023年04月15日
    浏览(13)
  • C++类与对象(下)

    C++类与对象(下)

    创建对象时,编译器会调用构造函数给对象中的成员变量一个合适的初始值。 虽然上述构造函数调用时,每个成员变量都有一个初始值了,但是这并不能称为类对象成员的初始化, 构造函数体中的语句只能称为赋初值 ,而不能称为初始化,因为 初始化只能初始一次,而构造

    2024年02月11日
    浏览(9)
  • [C++]类与对象下篇

    [C++]类与对象下篇

    目录 类与对象下篇::                             1.再谈构造函数                             2.static成员                             3.友元                             4.内部类                             5.匿名对象                             6.拷贝

    2023年04月25日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包