C++零基础教程(类的继承)

简介: C++零基础教程(类的继承)

前言

本篇文章我们来讲解类的继承,继承在C++中是非常重要的概念,这里需要大家认真的学习一下。

一、类的组合关系

类的组合关系是一种在面向对象编程中常见的关系类型,它描述了一个类由其他类的对象作为成员来组成的情况。在组合关系中,一个类包含了其他类的对象作为自己的成员,这些成员对象的生命周期与包含它们的类对象的生命周期相关联。

组合关系通常用于表示"拥有"的关系,表示一个类作为另一个类的一部分存在。这种关系是一种强耦合的关系,所以在组合关系中,包含类的对象负责创建和销毁其成员对象。

下面我们以一个简单的代码示例来解释类的组合关系:

class Engine {
public:
    void start() {
        // 启动引擎的逻辑
    }
    void stop() {
        // 停止引擎的逻辑
    }
};
class Car {
private:
    Engine engine;
public:
    void startCar() {
        engine.start();
    }
    void stopCar() {
        engine.stop();
    }
};

在上述示例中,Engine 类表示一台发动机,它具有启动和停止的功能。Car 类表示一辆汽车,它使用了一个 Engine 对象作为其成员。这里 Car 类与 Engine 类之间存在组合关系,因为 Car 类拥有一个 Engine 对象作为其一部分。

通过组合关系,Car 类可以在自己的方法中调用 Engine 类的方法,实现了汽车的启动和停止操作。而 Engine 对象的生命周期与 Car 对象的生命周期相关联,当 Car 对象被创建时,Engine 对象也会被创建,并且当 Car 对象被销毁时,Engine 对象也会被销毁。

总结来说,类的组合关系描述了一个类通过将其他类的对象作为自己的成员来构成的关系,具有强耦合性,成员对象的生命周期与包含它们的类对象相关联。组合关系用于表示"拥有"的关系,允许包含类访问和操作成员对象的功能。

二、类的继承

在C++中,继承是一种面向对象编程的重要概念,它允许一个类(称为派生类)继承另一个类(称为基类或父类)的属性和方法。通过继承,派生类可以重用基类的代码,并且可以在不修改基类的情况下添加自己的特定功能。

C++中的继承分为几种类型:

1.公有继承(public inheritance):基类的公有成员在派生类中仍然是公有成员,基类的保护成员在派生类中变为保护成员,基类的私有成员在派生类中不可直接访问。公有继承使用关键字public来进行声明。

2.保护继承(protected inheritance):基类的公有和保护成员在派生类中变为保护成员,基类的私有成员在派生类中不可直接访问。保护继承使用关键字protected来进行声明。

3.私有继承(private inheritance):基类的所有成员在派生类中都变为私有成员,基类的成员在派生类中不可直接访问。私有继承使用关键字private来进行声明。

以下是一个简单的C++代码示例来解释继承的概念:

#include <iostream>
using namespace std;
class Animal {
protected:
    string name;
public:
    Animal(string name) {
        this->name = name;
    }
    void eat() {
        cout << name << " is eating." << endl;
    }
};
class Dog : public Animal {
public:
    Dog(string name) : Animal(name) {
    }
    void bark() {
        cout << name << " is barking." << endl;
    }
};
int main() {
    Dog dog("Buddy");
    dog.eat();    // 输出:Buddy is eating.
    dog.bark();   // 输出:Buddy is barking.
    return 0;
}

在上述示例中,Animal 类是基类,它有一个受保护的属性 name 表示动物的名字,以及一个公共方法 eat() 表示动物的进食行为。

Dog 类是派生类,通过关键字 public 继承了 Animal 类。子类可以继承基类的公有和保护成员,因此 Dog 类中可以访问和使用 name 属性和 eat() 方法。此外,Dog 类还新增了一个独有的方法 bark() 表示狗的叫声。

通过继承,我们在主函数中创建了一个 Dog 对象,并且可以调用其继承自基类的 eat() 方法和派生类新增的 bark() 方法。

继承的主要优势在于代码重用和扩展性。子类可以重用基类的代码,从而减少了重复编写相似功能的工作,并提高了代码的可维护性。同时,子类可以在继承的基础上添加、修改和重写基类的属性和方法,以满足特定的需求。

三、父类构造函数和子类构造函数的关系

创建子类对象时,首先会执行父类的构造函数,然后再执行子类的构造函数。这是因为子类继承了父类的成员,需要先初始化父类的成员,然后再初始化子类自己的成员。

class Base {
public:
    Base() {
        // Base类的构造函数实现
        cout << "Base类的构造函数被调用" << endl;
    }
};
class Derived : public Base {
public:
    Derived() {
        // Derived类的构造函数实现
        cout << "Derived类的构造函数被调用" << endl;
    }
};
int main() {
    Derived obj; // 创建Derived类的对象
    return 0;
}

输出结果将会是:

Base类的构造函数被调用
Derived类的构造函数被调用

从输出结果可以看出,创建Derived类的对象时,先调用了Base类的构造函数,然后才调用Derived类的构造函数。

四、父类析构函数和子类析构函数

在C++中,析构函数用于释放对象占用的资源,并在对象销毁时执行一些清理操作。当一个对象被销毁时,先调用子类的析构函数,然后再调用父类的析构函数。这是因为派生类继承了父类的成员,需要先释放派生类自己的资源,然后再释放父类的资源。

父类的析构函数通常被声明为虚函数,以便正确地销毁派生类对象。通过虚函数的多态性,当使用基类指针或引用指向派生类对象时,可以通过基类的指针或引用来销毁对象而调用相应的析构函数。

下面是一个简单的示例来说明父类析构函数和子类析构函数的调用顺序:

#include <iostream>
using namespace std;
class Base {
public:
    Base() {
        cout << "Base类的构造函数被调用" << endl;
    }
    virtual ~Base() {
        cout << "Base类的析构函数被调用" << endl;
    }
};
class Derived : public Base {
public:
    Derived() {
        cout << "Derived类的构造函数被调用" << endl;
    }
    ~Derived() override {
        cout << "Derived类的析构函数被调用" << endl;
    }
};
int main() {
    Derived obj; // 创建Derived类的对象
    return 0;
}

输出结果将会是:

Base类的构造函数被调用
Derived类的构造函数被调用
Derived类的析构函数被调用
Base类的析构函数被调用

从输出结果可以看出,当创建Derived类的对象时,先调用了Base类的构造函数,然后再调用了Derived类的构造函数。当销毁对象时,先调用了Derived类的析构函数,然后再调用了Base类的析构函数。这个顺序保证了销毁对象的正确性。

总结

本篇文章主要讲解到了继承,这个概念需要大家牢牢掌握,在继承中大家需要注意public ,protected,private这三个访问权限的不同区别。


相关文章
|
2月前
|
编译器 C++ 开发者
【C++】继承
C++中的继承是面向对象编程的核心特性之一,允许派生类继承基类的属性和方法,实现代码复用和类的层次结构。继承有三种类型:公有、私有和受保护继承,每种类型决定了派生类如何访问基类成员。此外,继承还涉及构造函数、析构函数、拷贝构造函数和赋值运算符的调用规则,以及解决多继承带来的二义性和数据冗余问题的虚拟继承。在设计类时,应谨慎选择继承和组合,以降低耦合度并提高代码的可维护性。
36 1
【C++】继承
|
2月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
63 2
|
2月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
113 5
|
2月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
112 4
|
2月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
152 4
|
3月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
35 4
|
3月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
34 4
|
3月前
|
算法 数据挖掘 Shell
「毅硕|生信教程」 micromamba:mamba的C++实现,超越conda
还在为生信软件的安装配置而烦恼?micromamba(micromamba是mamba包管理器的小型版本,采用C++实现,具有mamba的核心功能,且体积更小,可以脱离conda独立运行,更易于部署)帮你解决!
87 1
|
3月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
33 1
|
3月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)