C++继承和多态
最后发布时间:2020-07-05 09:01:57
浏览量:
C++11引入final特殊标识符,可以使得类不能被继承
class B final {};
class D : public B {};
继承基类构造函数
using A::A; 继承所有基类ctor
继承中的默认构造函数
若基类constructor未被显式调用,基类的默认构造函数就会被调用
构造链和析构链
构造函数链:父先子后
析构函数链:子先父后
解决名字隐藏
class P {
public:
void f() {}
};
class C :public P {
public:
using P::f; //此处不带小括号*
void f(int x) {}
};
int main() {
C c;
c.f();
}
重定义函数
实现运行时多态
基类定义了虚同名函数,那么派生类中的同名函数自动变为虚函数
运行时多态的总结
- 通过派生类对象访问同名函数,是静态联编
- 通过基类对象的指针访问同名函数,是静态联编
- 通过基类对象的指针或引用访问同名虚函数,是动态联编
静态联编的简单示例
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特殊标识符,指定派生类不能覆写虚函数
访问控制
抽象类与纯虚函数
virtual double getArea() = 0; // 在Shape类中
向上转换和向下转换
运行时查询类型的信息
#include <typeinfo> //使用typeid,需要包含此头文件
class A {};
A a{};
auto& t1 = typeid(a);
if (typeid(A) == t1) {
std::cout << "a has type "
<< t1.name() << std::endl;
}