C++ 面向对象与类

梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)


  本教程将从面向对象的核心概念出发,系统讲解C++类的定义、实现、对象实例化,以及面向对象三大特性中的继承和多态,帮助你掌握C++面向对象编程的核心思想和实践技巧。

教程目录导航

一、面向对象核心概念

1.1 面向过程 vs 面向对象

编程范式是编写程序的方法论,C++支持面向过程和面向对象两种核心范式,二者的核心思想存在本质差异:

维度 面向过程(Procedure-Oriented) 面向对象(Object-Oriented)
核心思想 以“过程”为中心,将程序拆解为函数的集合 以“对象”为中心,将程序拆解为对象的交互
设计思路 关注“怎么做”,按步骤实现功能 关注“谁来做”,将数据和行为封装给对象
数据与函数 数据和函数分离,函数操作外部数据 数据和函数封装为一体,仅通过接口访问
扩展性 扩展困难,修改需改动大量代码 易扩展,通过继承/多态实现复用和扩展
典型应用 小型工具、简单算法(如计算器、排序) 大型软件、复杂系统(如游戏、框架)

1.2 类(Class)的概念

类是C++面向对象编程的核心载体,是对一类具有相同属性和行为的事物的抽象描述:

1.3 对象(Object)的概念

对象是类的实例化产物,是类模板创建的具体实体:

示例类比:

类 = 汽车设计图纸(定义了汽车的属性:颜色、排量;行为:启动、刹车)

对象 = 具体的一辆宝马车、一辆奔驰车(拥有自己的颜色/排量,可执行启动/刹车操作)

二、类的基本组成

2.1 成员变量(属性)

成员变量是类的“数据部分”,用于描述对象的状态和特征,也称为属性数据成员

2.2 成员函数(方法)

成员函数是类的“行为部分”,用于操作成员变量,实现对象的功能,也称为方法成员方法

2.3 访问权限控制

C++通过访问权限修饰符控制类成员的可见性,实现封装性,核心包含三种权限:

权限修饰符 类内访问 类外访问 子类访问
public(公有)
protected(保护) ×
private(私有) × ×

注意:

三、类的定义与实现

3.1 类的声明(类体)

类的声明使用class关键字,语法格式如下:


class 类名 {
    // 访问权限修饰符(默认private)
    public:
        // 公有成员变量/函数(对外接口)
    protected:
        // 保护成员变量/函数(子类可访问)
    private:
        // 私有成员变量/函数(仅类内可访问)
}; // 注意分号结尾
        

示例:声明一个Person类


class Person {
    // 私有成员(默认)
    char m_name[20];  // 姓名
    int m_age;        // 年龄
    float m_height;   // 身高

public:
    // 公有成员函数(对外接口)
    void setInfo(const char* name, int age, float height); // 设置信息
    void showInfo();  // 显示信息
    int getAge();     // 获取年龄
    void setAge(int age); // 设置年龄
};
        

3.2 成员函数的实现(内联/外部)

方式1:类内实现(内联函数)

成员函数直接写在类体内,自动成为内联函数(适合简单函数):


class Person {
private:
    int m_age;

public:
    // 类内实现(内联函数)
    int getAge() {
        return m_age;
    }
};
        

方式2:类外实现(作用域解析符::)

成员函数在类外实现,需使用类名::函数名指定作用域:


// 类的声明
class Person {
private:
    char m_name[20];
    int m_age;
    float m_height;

public:
    void setInfo(const char* name, int age, float height);
    void showInfo();
};

// 类外实现成员函数
void Person::setInfo(const char* name, int age, float height) {
    strcpy(m_name, name);
    m_age = age;
    m_height = height;
}

void Person::showInfo() {
    cout << "姓名:" << m_name << endl;
    cout << "年龄:" << m_age << endl;
    cout << "身高:" << m_height << "m" << endl;
}
        

3.3 构造函数与析构函数

构造函数和析构函数是类的特殊成员函数,负责对象的初始化和资源释放:

构造函数(Constructor)

用于对象创建时初始化成员变量,特点:


class Person {
private:
    char m_name[20];
    int m_age;

public:
    // 无参构造函数
    Person() {
        strcpy(m_name, "未知");
        m_age = 0;
        cout << "无参构造函数调用" << endl;
    }

    // 有参构造函数(重载)
    Person(const char* name, int age) {
        strcpy(m_name, name);
        m_age = age;
        cout << "有参构造函数调用" << endl;
    }

    void showInfo() {
        cout << "姓名:" << m_name << " 年龄:" << m_age << endl;
    }
};
        

析构函数(Destructor)

用于对象销毁时释放资源(如堆内存、文件句柄),特点:


class Person {
private:
    char* m_name; // 堆区字符串

public:
    // 构造函数:分配堆内存
    Person(const char* name) {
        m_name = new char[strlen(name) + 1];
        strcpy(m_name, name);
    }

    // 析构函数:释放堆内存
    ~Person() {
        delete[] m_name;
        m_name = nullptr;
        cout << "析构函数:释放内存" << endl;
    }
};
        

四、对象的定义与实例化

4.1 对象的创建方式

C++中对象的创建主要有三种方式,对应不同的内存区域:

方式1:栈区创建(直接实例化)


int main() {
    // 栈区创建对象,自动调用构造函数
    Person p1; // 无参构造
    Person p2("张三", 18); // 有参构造
    
    // 栈区对象销毁时自动调用析构函数
    return 0;
}
        

方式2:堆区创建(new关键字)


int main() {
    // 堆区创建对象,返回指针
    Person* p3 = new Person(); // 无参构造
    Person* p4 = new Person("李四", 20); // 有参构造
    
    // 手动释放堆区对象(否则内存泄漏)
    delete p3;
    delete p4;
    p3 = nullptr;
    p4 = nullptr;
    
    return 0;
}
        

方式3:静态对象(静态存储区)


int main() {
    // 静态对象,程序结束时才销毁
    static Person p5("王五", 22);
    return 0;
}
        

4.2 对象成员的访问

根据对象类型,使用不同的访问运算符:

普通对象:. 运算符


Person p("赵六", 19);
p.showInfo(); // 调用成员函数
p.setAge(20); // 修改私有成员(通过公有接口)
        

指针对象:-> 运算符


Person* p = new Person("孙七", 21);
p->showInfo(); // 调用成员函数
p->setAge(22); // 修改私有成员
delete p;
        

4.3 对象的内存布局

五、类的继承

继承是面向对象三大特性之一,允许新类(子类/派生类)复用旧类(父类/基类)的属性和方法,实现代码复用和扩展。

5.1 继承的基本语法


// 基类(父类)
class Person {
protected:
    char m_name[20];
    int m_age;

public:
    Person(const char* name, int age) {
        strcpy(m_name, name);
        m_age = age;
    }

    void showBaseInfo() {
        cout << "姓名:" << m_name << " 年龄:" << m_age << endl;
    }
};

// 派生类(子类):继承Person
class Student : public Person {
private:
    float m_score; // 新增成员

public:
    // 子类构造函数:必须调用父类构造函数初始化父类成员
    Student(const char* name, int age, float score) : Person(name, age) {
        m_score = score;
    }

    // 新增成员函数
    void showStudentInfo() {
        showBaseInfo(); // 调用父类成员函数
        cout << "成绩:" << m_score << endl;
    }
};

// 测试继承
int main() {
    Student stu("周八", 18, 92.5);
    stu.showStudentInfo(); // 子类对象可调用自身和父类的公有/保护成员
    return 0;
}
        

5.2 继承方式(public/protected/private)

继承方式决定了父类成员在子类中的访问权限:

父类权限 public继承 protected继承 private继承
public public protected private
protected protected protected private
private 不可访问 不可访问 不可访问

常用继承方式:

实际开发中优先使用public继承,protected/private继承会限制子类对父类成员的访问,仅在特殊场景使用。

5.3 继承的特性与注意事项

六、类的多态性

多态是面向对象三大特性之一,指“同一接口,不同实现”,分为静态多态和动态多态。

6.1 静态多态(编译期多态)

静态多态在编译阶段确定调用的函数,核心实现方式:函数重载、模板。

示例:函数重载(同一类内同名函数,参数列表不同)


class Calculator {
public:
    // 重载:int类型加法
    int add(int a, int b) {
        return a + b;
    }

    // 重载:float类型加法
    float add(float a, float b) {
        return a + b;
    }

    // 重载:三个int类型加法
    int add(int a, int b, int c) {
        return a + b + c;
    }
};

int main() {
    Calculator calc;
    cout << calc.add(1, 2) << endl;        // 调用int版本
    cout << calc.add(1.5f, 2.5f) << endl;  // 调用float版本
    cout << calc.add(1, 2, 3) << endl;     // 调用三个int版本
    return 0;
}
        

6.2 动态多态(运行期多态)

动态多态在运行阶段确定调用的函数,核心是虚函数(virtual)纯虚函数,满足三个条件:

示例:虚函数实现动态多态


// 父类:动物
class Animal {
public:
    // 虚函数
    virtual void makeSound() {
        cout << "动物发出声音" << endl;
    }

    // 虚析构函数(子类有堆内存时必须声明)
    virtual ~Animal() {}
};

// 子类:猫
class Cat : public Animal {
public:
    // 重写父类虚函数
    void makeSound() override {
        cout << "喵喵喵" << endl;
    }
};

// 子类:狗
class Dog : public Animal {
public:
    // 重写父类虚函数
    void makeSound() override {
        cout << "汪汪汪" << endl;
    }
};

// 测试动态多态
int main() {
    Animal* animal1 = new Cat();
    Animal* animal2 = new Dog();

    // 运行时确定调用子类的函数
    animal1->makeSound(); // 输出:喵喵喵
    animal2->makeSound(); // 输出:汪汪汪

    // 释放内存
    delete animal1;
    delete animal2;
    return 0;
}
        

纯虚函数与抽象类

纯虚函数是没有实现的虚函数,包含纯虚函数的类为抽象类,不能实例化,仅作为父类被继承:


// 抽象类(包含纯虚函数)
class Shape {
public:
    // 纯虚函数(=0表示无实现)
    virtual float getArea() = 0;

    virtual ~Shape() {}
};

// 子类:矩形(必须实现纯虚函数)
class Rectangle : public Shape {
private:
    float m_width;
    float m_height;

public:
    Rectangle(float w, float h) : m_width(w), m_height(h) {}

    // 实现纯虚函数
    float getArea() override {
        return m_width * m_height;
    }
};

int main() {
    // Shape s; // 错误:抽象类不能实例化
    Shape* rect = new Rectangle(5, 3);
    cout << "矩形面积:" << rect->getArea() << endl; // 输出:15
    delete rect;
    return 0;
}
        

6.3 多态的应用场景

七、注意事项

八、总结

掌握C++类和面向对象的核心思想,是从“新手”到“进阶”的关键一步。面向对象的封装、继承、多态三大特性,是构建大型、可维护C++程序的基础。


返回顶部