C++ 继承、派生、多态

继承就是在一个已存在的类的基础上建立一个新的类。

已存在的类称为基类,又称父类;新建立类称为派生类,又称为子类

继承允许我们依据另一个类来定义一个类,不需要重新编写一部分的数据成员和成员函数,达到了重用代码功能和提高执行效率的效果。

基类与派生类

一个类可以派生自多个类,从多个基类继承数据和函数。我们使用一个类派生列表来指定基类。

class derived-class: access-specifier base-class

其中,访问修饰符 access-specifierpublicprotectedprivate 其中的一个,如果未指定则默认 private

搬运一个例子

class Shape {
public:
    void setWidth(int w) {
        width = w;
    }
    void setHeight(int h) {
        height = h;
    }
protected:
    int width;
    int height;
};
class Rectangle: public Shape {
public:
    int getArea() {
        return (width * height);
    }
};
int main(void) {
    Rectangle Rect;
    Rect.setWidth(5);
    Rect.setHeight(7);
    cout << "Total area: " << Rect.getArea() << endl;
}

派生类继承了基类的属性,继承了基类的行为,可以添加额外的行为,也可以重新定义这些行为。

若基类定义的数据成员和派生类添加的数据成员同名,基类数据成员被覆盖。注意,即使函数名相同,参数不同,也无法调用基类函数。

在访问时,句柄的类型决定哪个类的成员被访问。使用对象名或引用访问同名成员,根据引用的类型决定,使用基类指针访问同名的成员,根据指针类型决定。

访问控制

派生类可以访问基类中所有的非私有成员。一个派生类继承了除去构造函数、析构函数、重载运算符、友元函数以外所有的基类方法.

不同继承类型的规则如下

  • 公有继承(public):
    • 基类的公有成员也是派生类的公有成员
    • 基类的保护成员也是派生类的保护成员
    • 基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有保护成员来访问。
  • 保护继承(protected):
    • 基类的公有保护成员将成为派生类的保护成员。
  • 私有继承(private):
    • 基类的公有保护成员将成为派生类的私有成员。

基类的友元函数可以访问基类中的私有成员,以及派生类从基类中继承的成员。派生类中的友元函数只能访问派生类的私有成员,而不能访问基类中的私有成员。

拷贝构造函数仅用于同类拷贝或派生类向基类拷贝,而不能用于基类向派生类拷贝。

虚拟与多态

虚函数与纯虚函数

定义虚函数是为了允许用基类的指针来调用子类的这个函数。

例如以下程序的输出结果为 B

class A {
public:
    virtual void foo() {
        cout<<"A"<<endl;
    }
};
class B:public A {
public:
    void foo() {
        cout<<"B"<<endl;
    }
};
int main() {
    A *a = new B();
    a->foo();
}

在这里,调用的是哪个函数不是在编译时刻被确定的,而是在运行时刻被确定的。换言之,在编译时,并不知道被调用的是基类的函数还是哪个派生类的函数。

定义一个函数为纯虚函数,代表函数没有被实现,只是为了实现一个接口。它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。定义方式为

virtual void func()=0;

多态

在面向对象语言中,接口的多种不同的实现方式即为多态。

类的多态允许将子类类型的指针赋值给父类类型的指针。赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。

从应用的角度说,在基类的函数前加上 virtual 关键字声明为虚函数后,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。

所有虚类的对象里面会自动加上一个隐藏指针,指向一张属于类的表 vtable,里是所有 virtual 函数的地址。

带有虚函数的类

每一个类都有虚表,且虚表可以继承。

如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。

如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现。

如果派生类有自己的虚函数,那么虚表中就会添加该项。

所谓类的多态性,即将基类的函数定义为虚函数,在派生类中重写,运行时将会根据对象的实际类型来调用相应的函数。

注意区分类的多态性与函数的多态性。函数的多态性指一个函数被定义成多个不同参数的函数,调用这个函数时,就会调用不同的同名函数。

总结

派生类继承自基础类,可以描述基类对象集合中一组更细化、特殊的对象。派生类继承了基类的属性,继承了基类的行为,可以添加额外的行为,也可以重新定义这些行为。

虚函数是为了允许用基类的指针来调用子类的这个函数。调用的是哪个函数不是在编译时刻被确定的,而是在运行时刻被确定的。

定义一个函数为纯虚函数,代表函数没有被实现,只是为了实现一个接口。它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。

类的多态允许将子类类型的指针赋值给父类类型的指针。赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。

原文链接: https://www.cnblogs.com/mollnn/p/12612713.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++ 继承、派生、多态

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/339152

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午11:57
下一篇 2023年3月1日 下午11:57

相关推荐