C++继承和多态

最后发布时间:2020-07-05 09:01:57 浏览量:

158

158

C++11引入final特殊标识符,可以使得类不能被继承

class B final {};
class D : public B {};

继承基类构造函数

using A::A; 继承所有基类ctor

继承中的默认构造函数

若基类constructor未被显式调用,基类的默认构造函数就会被调用

图片alt

图片alt

构造链和析构链

构造函数链:父先子后
析构函数链:子先父后

解决名字隐藏

class P {
public:
  void f() {}
};
class C :public P {
public:
  using P::f; //此处不带小括号*
  void f(int x) {}
};
int main() {
  C c;
  c.f();
}

重定义函数

图片alt

图片alt

实现运行时多态

图片alt

图片alt

基类定义了虚同名函数,那么派生类中的同名函数自动变为虚函数

运行时多态的总结

  • 通过派生类对象访问同名函数,是静态联编
  • 通过基类对象的指针访问同名函数,是静态联编
  • 通过基类对象的指针或引用访问同名虚函数,是动态联编

静态联编的简单示例

class P           { public: f(){…} }; //父类
class C: public P { public: f(){…} }; //子类
main () {
    P p;   C c;
    p.f();         //调用P::f()
    c.f();         //调用C::f()
}

说明: 对象是什么类型,就调什么类型

通过基类指针访问同名函数的示例

class P           { public: f(){…} }; //父类
class C: public P { public: f(){…} }; //子类
main () {
    P* ptr;   P p;   C c;
    ptr = &p;
    ptr->f();      // 调用P::f()
    ptr=&c;
    ptr->f();      // 调用P::f()
}

说明: 指针是什么类型,就调什么类型

动态联编的简单示例-指针形式

class P           { public: virtual f(){…} }; //父类
class C: public P { public: f(){…} }; //子类,f自动virtual
main () {
    P* ptr;   P p;   C c;
    ptr = &p;
    ptr->f();    //调用P::f()
    ptr=&c;
    ptr->f();    //调用C::f()
}

说明: 函数虚,不看指针看真对象

动态联编的简单示例-引用形式

class P           { public: virtual f(){…} }; //父类
class C: public P { public: f(){…} }; //子类,f自动virtual
main () {
    P p;   C c;
    P& pr1 = p;
    pr1.f();      //调用P::f()
    P& pr2 = c;
    pr2.f();      //调用C::f()
}

说明: 函数虚,不看引用看真对象

override显式声明覆写

class A {
public:
  virtual void foo() {}
  void bar() {}
};
class B : public A {
public:
  void foo() const override { // 错误: B::foo 不覆写 A::foo
  }                           // (签名不匹配)
  void foo() override;   // OK : B::foo 覆写 A::foo
  void bar() override {} // 错误: A::bar 非虚
};
void B::foo() override {// 错误: override只能放到类内使用

override的价值在于:避免程序员在覆写时错命名或无虚函数导致隐藏bug

final 显式声明禁止覆写

struct Base {
    virtual void foo();
};
struct A : Base 
{ 
    void foo() final; // A::foo 被覆写且是最终覆写
    void bar() final; // 错误:非虚函数不能被覆写或是 final
};
struct B final : A // struct B 为 final,不能被继承
{
    void foo() override; // 错误: foo 不能被覆写,因为它在 A 中是 final
};

C++11引入final特殊标识符,指定派生类不能覆写虚函数

访问控制

图片alt

图片alt

抽象类与纯虚函数

virtual double getArea() = 0;  // 在Shape类中

向上转换和向下转换

图片alt

图片alt

运行时查询类型的信息

#include <typeinfo>  //使用typeid,需要包含此头文件 
class A {};
A a{};
  auto& t1 = typeid(a);
  if (typeid(A) == t1) {
    std::cout << "a has type " 
              << t1.name() << std::endl;
  }