跳转至

07 ⚓︎

666 个字 104 行代码 预计阅读时间 5 分钟

C++ 相比 C 的一大特征便是面向对象编程(object-oriented programming, OOP,而类(classes)便是 OOP 的一大表现形式。类是一种自定义的类型,允许用户通过成员变量和成员函数封装数据和功能。前面讲到的容器本质上是定义在 STL 的类。

结构体和类的区别:

classes containing a sequence of objects of various typs, a set of functions for manipulating these objects, and a set of restriction on the access of these objects and function;

structrues which are classes without access restriction;

-- Bjarne Stroustrup

也就是说,结构体的所有字段都是公共的(public,任何人都可以改变它们的值,这样就会发生意想不到的不良行为。而类具备公共(public)和私有(private)两块区域,任何用户均可以使用公共区域内的东西,但访问私有区域的东西时会受限。

class className
{
    private:
    // ...

    public:
    // ...
};

在创建类的时候,我们往往将整个类放在头文件(.h)和源文件(.cpp)内。

  • 头文件
    • 用于定义类的接口(interface)
    • 包括:函数原型、变量声明、类定义、类型定义、宏和常量、模板定义
  • 源文件
    • 用于定义函数和类的实现(侧重逻辑
    • 包括:函数实现、可执行代码

组成⚓︎

  • 构造函数(constructor)
  • 私有成员函数 / 变量
  • 公共成员函数(为用户提供接口)
  • 析构函数(destructor)

之后就以 Student 类为例介绍类。

Student.h
class Student
{
    private:
        std::string name;
        std::string state;
        int age;

    public: 
        // constructor
        Student(std::string name, std::string state, int age);
        // method
        std::string getName();
        std::string getState();
        int getAge();
};

构造函数⚓︎

构造函数用于初始化新建对象的状态。

Student.cpp
#include "Student.h"
#include <string>

// 构造函数默认参数
Student::Student()
{
    name = "John Appleseed";
    state = "CA";
    age = 18;
}

// 构造函数1
Student::Student(std::string name, std::string state, int age)
{
    this->name = name;
    this->state = state;
    this->age = age;
}
  • 在定义成员函数时,我们需要将类名作为函数的名称空间
  • 使用关键词 this 解决类的成员变量和形参同名带来的歧义问题
  • 如果调用成员函数时某些参数未指定,那么编译器会选择程序员设好的默认参数。
// 构造函数2,类似统一初始化的方法
Student::Student(std::string name, std::string state, int age): name{name}, state{state}, age{age} {}

析构函数⚓︎

Student::~Student()
{
    // free/deallocate any data here
}

如果类里面采用动态分配数据的方式,则析构函数是必需的。当程序运行到某个对象的活动范围之外时会自动调用析构函数。

类型别名⚓︎

类型别名(type aliasing)允许创建某个类型的同义标识符,比如:

Student.h
class Student
{
    private:
        // type aliasing
        using String = std::string;
        String name;
        String state;
        int age;

    public: 
        // constructor
        Student(std::string name, std::string state, int age);
        // method
        String getName();
        String getState();
        int getAge();
};

继承⚓︎

简单来说,继承(inheritance)就是从允许我们在某个类(称为「基类)的基础上进行扩展,形成新的类(称为「子类,它具有以下特点:

  • 多态性(polymorphism:不同的对象需要有相同的接口
  • 扩展性(extensibility:继承能够通过创建一些具体属性扩展某个类

例子

.h file
// base class
class Shape
{
    public:
        virtual double area() const = 0;
};

// subclass
class Circle : public Shape
{
    public:
        // constructor
        Circle(double radius): _radius(radius) {};
        double area() const
        {
            return 3.14 * _radius * _radius;
        }
    private:
        double _radius;
}

注:Shape 类中用到了虚拟继承,关键词virtual` 表示该(基类)的成员能够被子类覆写

Another .h file
// base class
class Shape
{
    public:
        virtual double area() const = 0;
};

// subclass
class Rectangle : public Shape
{
    public:
        // constructor
        Rectangle(double height, double width): _height(height), _width(width) {};
        double area() const
        {
            return _width * _height;
        }
    private:
        double _width, _height;
}  

评论区

如果大家有什么问题或想法,欢迎在下方留言~