C++学习笔记——继承和动态内存分配

发布时间:2024年01月11日

目录

一、继承

二、动态内存分配

三、继承的细节

四、动态内存分配细节

五、一个动物园管理系统


继承和动态内存分配是C++中两个重要的概念

一、继承

继承是C++中面向对象编程的一个重要特性,它允许我们创建一个新类,该类从现有的类中继承属性和方法,并可以添加新的属性和方法。这样做可以提高代码的重用性和可维护性。

继承的语法格式如下:

class ChildClass : public ParentClass
{
    // 子类定义
};

在上述代码中,ChildClass 是子类,ParentClass 是父类。子类通过 : 连接符指定其继承自父类,并通过 publicprivateprotected 访问控制符来指定父类的成员对子类的可见性。

继承有三种类型:公有继承、私有继承和保护继承。公有继承表示子类可以访问父类的公共成员,私有继承表示子类只能访问父类的私有成员,保护继承表示子类可以访问父类的保护成员。

二、动态内存分配

在 C++ 中,动态内存分配可以通过 newdelete 运算符实现。动态内存分配可以使程序更加灵活,可以在程序运行时动态地分配和释放内存。

动态内存分配的基本语法如下:

new type;
delete pointer;

其中,type 表示需要分配内存的类型,可以是内置类型、指针类型或用户自定义类型。pointer 表示需要释放的指针。

使用 new 运算符分配内存时,会在堆上分配一块内存,并返回指向该内存块的指针。例如:

int* p = new int; // 动态分配一个整型变量
*p = 10; // 对指针所指向的内存进行赋值
cout << *p << endl; // 输出 10

使用 delete 运算符释放内存时,需要注意以下几点:

  • 只能释放由 new 分配的内存。
  • 被释放的指针必须指向有效的内存。
  • 避免多次释放同一块内存。

例如:

delete p; // 释放由 p 指向的内存

在使用动态内存分配时,需要注意内存泄漏和空悬指针的问题。内存泄漏指程序中分配的内存没有被及时释放,造成内存浪费;空悬指针指指向已释放的内存的指针,访问空悬指针会导致程序崩溃。

三、继承的细节

当谈到继承时,它是面向对象编程的一个重要概念。它允许我们创建一个新类,该类从现有的类中继承属性和方法,并且可以添加新的属性和方法。这种方式可以提高代码的重用性和可维护性。

在C++中,继承使用关键字class来定义子类,并使用冒号:来指定继承的父类。语法格式如下:

class ChildClass : public ParentClass
{
    // 子类定义
};

在这个例子中,ChildClass是子类,ParentClass是父类。通过使用冒号连接符,我们指定子类继承自父类。public关键字表示继承方式为公有继承。公有继承意味着子类可以访问父类的公共成员。

除了公有继承,C++还支持私有继承和保护继承。私有继承使用private关键字,表示子类只能访问父类的私有成员。保护继承使用protected关键字,表示子类可以访问父类的保护成员。

子类可以对继承下来的属性和方法进行覆盖或扩展。如果子类定义了与父类相同名称的成员函数,则子类的成员函数将覆盖父类的成员函数。如果子类需要调用父类的同名成员函数,可以使用作用域解析运算符::来指定父类的名称。

四、动态内存分配细节

是C++中另一个重要的概念,它允许在程序运行时动态地分配和释放内存。C++提供了两个相关的运算符来进行动态内存分配:newdelete

使用new运算符可以在堆上分配一块内存,并返回指向该内存块的指针。语法格式如下:

type* pointer = new type;

其中,type表示需要分配内存的类型,可以是内置类型、指针类型或用户自定义类型。pointer是一个指针,用于存储分配内存的起始地址。

例如,我们可以动态分配一个整型变量,并使用指针对其进行操作:

int* p = new int; // 动态分配一个整型变量
*p = 10; // 对指针所指向的内存进行赋值

使用delete运算符可以释放通过new分配的内存。语法格式如下:

delete pointer;

其中,pointer是要释放的指针。注意以下几点:

  • 只能释放通过new分配的内存,不能释放栈上或全局变量的内存。
  • 被释放的指针必须指向有效的内存。
  • 避免多次释放同一块内存。

例如,我们可以使用delete释放先前动态分配的整型变量:

delete p; // 释放由p指向的内存

在使用动态内存分配时,需要注意内存泄漏和空悬指针的问题。内存泄漏指的是程序中分配的内存没有被及时释放,造成内存浪费。空悬指针是指指向已释放内存的指针,访问空悬指针可能导致程序崩溃。

五、一个动物园管理系统

这个系统可以管理动物园中的不同种类的动物,包括狮子、老虎和熊,并提供一些功能,如添加动物、显示动物列表和播放动物声音。

下面是使用C++语言实现的代码示例:

#include <iostream>
#include <vector>

// 动物类
class Animal {
protected:
    std::string name;
    int age;

public:
    // 构造函数
    Animal(std::string name, int age) {
        this->name = name;
        this->age = age;
    }

    // 纯虚函数,用于播放动物声音
    virtual void makeSound() = 0;

    // 获取动物名称
    std::string getName() {
        return name;
    }

    // 获取动物年龄
    int getAge() {
        return age;
    }
};

// 狮子类,继承自动物类
class Lion : public Animal {
public:
    // 调用基类的构造函数
    Lion(std::string name, int age) : Animal(name, age) {}

    // 实现纯虚函数,播放狮子声音
    void makeSound() override {
        std::cout << "狮子的声音:Roar!" << std::endl;
    }
};

// 老虎类,继承自动物类
class Tiger : public Animal {
public:
    // 调用基类的构造函数
    Tiger(std::string name, int age) : Animal(name, age) {}

    // 实现纯虚函数,播放老虎声音
    void makeSound() override {
        std::cout << "老虎的声音:Roar!" << std::endl;
    }
};

// 熊类,继承自动物类
class Bear : public Animal {
public:
    // 调用基类的构造函数
    Bear(std::string name, int age) : Animal(name, age) {}

    // 实现纯虚函数,播放熊的声音
    void makeSound() override {
        std::cout << "熊的声音:Growl!" << std::endl;
    }
};

// 动物园管理系统类
class ZooManagementSystem {
private:
    std::vector<Animal*> animals;  // 存储动物对象的指针容器

public:
    // 添加动物
    void addAnimal(Animal* animal) {
        animals.push_back(animal);
    }

    // 显示动物列表
    void displayAnimals() {
        for (const auto& animal : animals) {
            std::cout << "名称:" << animal->getName()
                      << " 年龄:" << animal->getAge() << std::endl;
            animal->makeSound();
            std::cout << std::endl;
        }
    }
};

int main() {
    // 创建动物园管理系统对象
    ZooManagementSystem zms;

    // 创建狮子对象并添加到动物园
    Lion* lion = new Lion("Simba", 5);
    zms.addAnimal(lion);

    // 创建老虎对象并添加到动物园
    Tiger* tiger = new Tiger("Richard", 4);
    zms.addAnimal(tiger);

    // 创建熊对象并添加到动物园
    Bear* bear = new Bear("Bobby", 3);
    zms.addAnimal(bear);

    // 显示动物列表和播放声音
    zms.displayAnimals();

    // 释放动态分配的内存
    delete lion;
    delete tiger;
    delete bear;

    return 0;
}

在这个案例中,我们定义了一个基类Animal和三个派生类LionTigerBear。基类Animal包含了动物的基本属性和纯虚函数makeSound,派生类继承了基类并实现了具体的声音。

ZooManagementSystem类中,我们使用一个指针容器std::vector<Animal*>来存储动物对象的指针。通过使用动态内存分配的方式,我们创建了狮子、老虎和熊的对象,并通过addAnimal方法将它们添加到动物园。然后,我们调用displayAnimals方法显示动物的信息和播放声音。

main函数中,我们创建了一个ZooManagementSystem对象,并动态分配了狮子、老虎和熊的对象。在程序结束之前,我们使用delete运算符释放了动态分配的内存。

文章来源:https://blog.csdn.net/m0_62338174/article/details/135516720
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。