什么是继承性?C++中如何实现继承? 继承的好处和注意事项有哪些?

一、继承性的概念

定义

在面向对象编程中,继承性是一种机制,它允许创建一个新的类(称为派生类或子类)从一个现有的类(称为基类或父类)获取成员变量和成员函数。简单来说,子类继承了父类的属性和行为,并且可以在此基础上添加新的特性或者修改从父类继承来的特性。

示例

以交通工具为例,假设Vehicle(交通工具)是一个基类,它有成员变量如speed(速度)和成员函数如move()(移动)。Car(汽车)类可以从Vehicle类继承,这样Car类就自动拥有了speed变量和move()函数,并且还可以添加自己特有的成员,如numberOfDoors(车门数量)和openDoor()(开门)函数。

二、C++ 中实现继承的方式

语法格式

在 C++ 中,通过在派生类定义时使用冒号:和关键字public(公有继承)、private(私有继承)或protected(保护继承)来指定继承方式,后面跟上基类名称。例如:

class Base {
    // 基类的成员声明
};
class Derived : public Base {
    // 派生类的成员声明
};

三种继承方式的区别

公有继承(public)

基类的公有成员在派生类中仍然是公有成员,基类的保护成员在派生类中仍然是保护成员,基类的私有成员不能被派生类直接访问。这种继承方式保持了基类接口的开放性,使得派生类对象可以像基类对象一样使用基类的公有成员函数。例如:

class Base {
public:
    void publicFunction() {}
protected:
    int protectedVariable;
private:
    int privateVariable;
};
class Derived : public Base {
public:
    void accessBaseMembers() {
        publicFunction(); 
        // 可以访问基类的公有成员函数
        protectedVariable = 10; 
        // 可以访问基类的保护成员变量
        // privateVariable = 20; 
        // 错误,不能访问基类的私有成员变量
    }
};

私有继承(private)

基类的公有成员和保护成员在派生类中都变成私有成员。这意味着派生类对象不能直接访问基类的公有成员函数,外部代码通过派生类对象也无法访问基类的任何成员。例如:

class Base {
public:
    void publicFunction() {}
protected:
    int protectedVariable;
};
class Derived : private Base {
public:
    void accessBaseMembers() {
        publicFunction(); 
        // 可以在派生类内部访问基类的公有成员函数,但在外部不可访问
        protectedVariable = 10; 
        // 可以在派生类内部访问基类的保护成员变量,但在外部不可访问
    }
};
int main() {
    Derived d;
    // d.publicFunction(); 
    // 错误,私有继承后基类的公有成员在派生类外部不可访问
    return 0;
}

保护继承(protected)

基类的公有成员和保护成员在派生类中都变成保护成员。这使得派生类的派生类(孙类)可以访问这些成员,但外部代码不能通过派生类对象访问基类的成员。例如:

class Base {
public:
    void publicFunction() {}
protected:
    int protectedVariable;
};
class Derived : protected Base {
public:
    void accessBaseMembers() {
        publicFunction(); 
        // 可以在派生类内部访问基类的公有成员函数,但在外部不可访问
        protectedVariable = 10; 
        // 可以在派生类内部访问基类的保护成员变量,但在外部不可访问
    }
};
class GrandDerived : public Derived {
public:
    void accessBaseMembersFurther() {
        publicFunction(); 
        // 可以访问,因为是保护继承,孙类可以访问基类的公有成员函数
        protectedVariable = 20; 
        // 可以访问,因为是保护继承,孙类可以访问基类的保护成员变量
    }
};

三、继承的好处

代码复用

可以避免重复编写相同的代码。例如,如果有多个类都具有一些相同的基本属性和行为,通过将这些共同的部分放在基类中,然后让其他类继承自这个基类,就可以减少代码量。像前面提到的交通工具的例子,不同类型的交通工具(汽车、自行车、飞机等)都有速度和移动的属性和行为,将这些放在Vehicle基类中,其他交通工具类继承后就不用再次定义这些基本的功能。

层次化设计和建模

能够更好地对现实世界中的对象关系进行建模。例如,在一个图形系统中,可以有一个基类Shape,它具有一些基本的属性如颜色、位置等,以及基本的行为如绘制函数draw()。然后不同的具体形状类(如Circle、Rectangle等)可以继承自Shape类,并且添加自己特有的属性(如Circle的半径)和行为(如根据半径来绘制圆的draw()函数实现)。这样的层次结构使得代码更加清晰,易于理解和维护。

可扩展性

方便对程序进行扩展。当需要添加新的功能或者新的类型时,只需要在派生类中进行添加即可。例如,在游戏开发中,如果有一个基类Character,代表游戏中的角色,具有基本的属性如生命值、攻击力等。当要添加一个新的角色类型,如Magician(魔法师),可以从Character类继承,然后添加魔法师特有的属性如魔法值、魔法技能等,而不需要修改原来的Character类以及其他非魔法师角色类的代码。

四、继承的注意事项

继承层次结构设计

设计继承层次结构时要谨慎,避免创建过于复杂或不合理的层次结构。如果层次结构太深或者太宽,可能会导致代码难以理解和维护。例如,不应该为了一点点差异就创建大量的子类,这样会使类的层次变得混乱。

基类和派生类的耦合性

继承会导致基类和派生类之间有一定的耦合性。当对基类进行修改时,可能会影响到派生类。例如,如果修改了基类的一个成员函数的接口(参数列表或返回值类型),那么所有派生类中重写或者调用这个函数的地方都可能需要修改。所以在设计基类时,要尽量考虑到其稳定性和通用性,避免频繁地修改基类接口。

继承中的函数重写(覆盖)规则

当派生类重写基类的函数时,函数的签名(函数名、参数列表、返回值类型等)需要满足一定的规则。在 C++ 中,函数签名要相同(协变返回类型除外),并且如果基类中的函数是虚函数,派生类中重写的函数也要是虚函数,以保证多态性的正确实现。否则可能会出现意想不到的结果。例如:

class Base {
public:
    virtual void print() {
        std::cout << "Base class print function" << std::endl;
    }
};
class Derived : public Base {
public:
    void print() {
        std::cout << "Derived class print function" << std::endl;
    }
};

在这个例子中,Derived类正确地重写了Base类的print函数,因为Base类中的print函数是虚函数,并且Derived类中的print函数签名和Base类中的相同,这样在使用多态性(通过基类指针或引用调用派生类对象的函数)时就可以正确地调用Derived类的print函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值