C++ 类的继承:构建代码复用与拓展的桥梁

#新星杯·14天创作挑战营·第11期#

在 C++ 的面向对象编程中,类的继承是一项极为重要的特性,它为代码的复用与拓展提供了强大的支持。通过继承,我们可以创建出具有层次结构的类,让新类能够自动获得已有类的属性和行为,并在此基础上进行扩展和修改。接下来,我们就深入探讨类的继承相关内容。

目录

一、确定类的层次

1.1 类层次的概念

1.2 如何确定类层次

二、继承的类型

2.1 公有继承

2.2 私有继承

2.3 保护继承

三、总结


一、确定类的层次

1.1 类层次的概念

类的层次结构就像是一棵家族树,顶层是基类(也称为父类),从基类派生出的类称为派生类(也称为子类)。派生类可以继承基类的成员变量和成员函数,并且可以添加自己特有的成员。合理确定类的层次结构,能够让代码的组织更加清晰,便于理解和维护。

1.2 如何确定类层次

在确定类层次时,需要从实际需求出发,找出具有共性的属性和行为,将它们抽象到基类中。例如,在一个图形绘制程序中,“图形” 可以作为基类,它包含一些通用的属性(如颜色)和行为(如绘制)。而 “圆形”“矩形” 等则可以作为派生类,它们继承 “图形” 基类的属性和行为,同时又有自己特有的属性(如圆形的半径、矩形的长和宽)和行为(如计算各自的面积)。

代码示例

// 基类:图形
class Shape {
protected:
    std::string color;
public:
    Shape(const std::string& c) : color(c) {}
    virtual void draw() const {
        std::cout << "绘制一个" << color << "的图形" << std::endl;
    }
};

// 派生类:圆形
class Circle : public Shape {
private:
    double radius;
public:
    Circle(const std::string& c, double r) : Shape(c), radius(r) {}
    void draw() const override {
        std::cout << "绘制一个半径为" << radius << "的" << color << "圆形" << std::endl;
    }
};

// 派生类:矩形
class Rectangle : public Shape {
private:
    double length;
    double width;
public:
    Rectangle(const std::string& c, double l, double w) : Shape(c), length(l), width(w) {}
    void draw() const override {
        std::cout << "绘制一个长为" << length << ",宽为" << width << "的" << color << "矩形" << std::endl;
    }
};

在这个例子中,Shape是基类,CircleRectangle是派生类。CircleRectangle继承了Shapecolor属性和draw函数,并且各自进行了扩展。

二、继承的类型

2.1 公有继承

公有继承是最常见的继承方式,其定义语法为:

class 派生类名 : public 基类名 {
    // 派生类的成员
};

在公有继承中,基类的公有成员在派生类中仍然是公有成员,基类的保护成员在派生类中仍然是保护成员。基类的私有成员在派生类中不可直接访问。

公有继承的特点

  • 派生类的对象可以直接访问从基类继承过来的公有成员。
  • 派生类的成员函数可以访问从基类继承过来的公有和保护成员。
  • 公有继承建立了 “是一种”(is-a)的关系,即派生类对象可以被视为基类对象使用。
class Base {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived : public Base {
public:
    void accessMembers() {
        publicMember = 10;  // 合法,派生类成员函数可访问继承的公有成员
        protectedMember = 20;  // 合法,派生类成员函数可访问继承的保护成员
        // privateMember = 30;  // 错误,派生类不能直接访问基类的私有成员
    }
};

int main() {
    Derived d;
    d.publicMember = 5;  // 合法,派生类对象可访问继承的公有成员
    // d.protectedMember = 6;  // 错误,派生类对象不能直接访问继承的保护成员
    return 0;
}

 公有继承常用于实现 “是一种” 的关系,比如 “圆形是一种图形”,“汽车是一种交通工具” 等。在这种情况下,派生类完全继承基类的接口,并且可以扩展自己的功能,同时保持与基类的类型兼容性。例如,在一个多态应用中,可以通过基类指针或引用操作派生类对象。

2.2 私有继承

私有继承的定义语法为:

class 派生类名 : private 基类名 {
    // 派生类的成员
};

在私有继承中,基类的公有成员和保护成员在派生类中都变为私有成员。基类的私有成员在派生类中仍然不可直接访问。

私有继承的特点

  • 派生类的对象不能直接访问从基类继承过来的任何成员。
  • 只有派生类的成员函数可以访问从基类继承过来的公有和保护成员。
  • 私有继承建立了 “根据某种实现”(is-implemented-in-terms-of)的关系,派生类复用了基类的实现细节,但不继承其接口。
class Base {
public:
    int publicMember;
protected:
    int protectedMember;
};

class Derived : private Base {
public:
    void accessMembers() {
        publicMember = 10;  // 合法,派生类成员函数可访问继承的公有和保护成员
        protectedMember = 20;
    }
};

int main() {
    Derived d;
    // d.publicMember = 5;  // 错误,派生类对象不能访问继承的公有成员
    // d.protectedMember = 6;  // 错误,派生类对象不能访问继承的保护成员
    return 0;
}

 私有继承常用于实现 “根据某种实现” 的关系,即派生类只是利用基类的实现细节,而不希望对外暴露基类的接口。它更像是一种实现层面的复用,而不是类型的继承。例如,当一个类需要复用另一个类的某些功能,但又不想让用户看到基类的接口时,可以使用私有继承。

2.3 保护继承

保护继承的定义语法为:

class 派生类名 : protected 基类名 {
    // 派生类的成员
};

保护继承的特点

  • 派生类的对象不能直接访问从基类继承过来的任何成员。
  • 派生类的成员函数可以访问从基类继承过来的公有和保护成员。
  • 派生类的派生类(即孙子类)的成员函数可以访问从基类继承过来的公有和保护成员(这些成员在派生类中变为保护成员)
class Base {
public:
    int publicMember;
protected:
    int protectedMember;
};

class Derived : protected Base {
public:
    void accessMembers() {
        publicMember = 10;  // 合法,派生类成员函数可访问继承的公有和保护成员
        protectedMember = 20;
    }
};

class GrandDerived : public Derived {
public:
    void accessBaseMembers() {
        publicMember = 30;  // 合法,孙子类成员函数可访问继承的公有和保护成员
        protectedMember = 40;
    }
};

 保护继承的使用场景相对较少,但在一些复杂的类层次结构中,当希望派生类的派生类能够访问基类的部分成员时,保护继承就可以发挥作用。例如,在一个多层继承的系统中,某些基类的成员需要对其直接派生类和间接派生类可见,但对外部不可见时,可以使用保护继承。

三、总结

类的继承是 C++ 面向对象编程中实现代码复用和拓展的重要手段。通过合理确定类的层次结构,以及选择合适的继承类型(公有继承、私有继承、保护继承),我们能够编写出结构清晰、可维护性强且功能丰富的程序。在实际编程中,需要根据具体的需求和设计目标来灵活运用类的继承特性,充分发挥其优势,让代码更加简洁高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值