zoukankan      html  css  js  c++  java
  • Effective C++ 条款9 决不在构造和析构过程后调用虚函数

    1. 在一个继承体系中,最底层的派生类在构造过程中,先初始化基类部分,再按继承层次依次初始化派生类部分,因此被构造的对象先作为一个基类对象,再按继承层次依次成为派生类对象,例如,在继承层次A→B→C→D中,构造一个D类对象,其依次经历了A→B→C→D的转变,因此对于以下代码:

    #include <iostream>
    using namespace std;
    class A{
    public:
        virtual void foo(){ cout << "A" << endl; }
        A(){ foo(); }
    };
    class B :public A{
    public:
        void foo(){ cout << "B" << endl; }
        B(){ foo(); }
    };
    class C :public B{
    public:
        void foo(){ cout << "C" << endl; }
        C(){ foo(); }
    };
    class D :public C{
    public:
        void foo(){ cout << "D" << endl; }
        D(){ foo(); }
    };
    int main() {
        D d;
        system("pause");
        return 0;
    }
    View Code

    运行结果为:

    可见,在构造函数中调用虚函数,不仅不能如愿调用底层派生类的虚函数,还会依次调用整个继承层次的虚函数.这就是不在构造过程中调用虚函数的原因,除此之外涉及到RTTI(Run-Time Type Information,运行时类型识别)时也会把对象按构造顺序依次视为A→B→C→D.

    2. 在A→B→C→D这个继承体系中,如果对一个D类对象调用析构函数,会依次调用D,C,B,A的析构函数,对象也依次经历了D→C→B→A的转变,同理,不要在析构函数中调用虚函数.

    3. 如果确实需要在构造函数中调用由类型确定的函数,可以”令derived classes将必要的构造信息向上传递至base class构造函数“替换虚函数的使用,例如:

    class A{
    public:
        void foo(){ cout << "A" << endl; }
        A(char ch='a'){ if(ch=='a') foo(); }
    };
    class B :public A{
    public:
        void foo(){ cout << "B" << endl; }
        B(char ch = 'b') :A(ch){ if (ch == 'b') foo(); }
    };
    class C :public B{
    public:
        void foo(){ cout << "C" << endl; }
        C(char ch = 'c') :B(ch){ if (ch == 'c') foo(); }
    };
    class D :public C{
    public:
        void foo(){ cout << "D" << endl; }
        D():C('d'){ foo(); }
    }; 
    View Code

    这样就可以确保调用合适的构造函数.

  • 相关阅读:
    多输出感知机及其梯度
    《机器学习实战》-线性回归
    《机器学习实战》-逻辑(Logistic)回归
    SQL Server 空间监测
    SQL Server 从数据库快照还原数据库
    SQL Server 创建数据库快照
    SQL Server 数据库的自动选项
    SQL Server 数据库游标选项
    SQL Server 数据库状态选项
    MYSQL 二进制还原
  • 原文地址:https://www.cnblogs.com/reasno/p/4750293.html
Copyright © 2011-2022 走看看