zoukankan      html  css  js  c++  java
  • Effective C++ 条款09:绝不在构造和析构过程中调用virtual函数

    规则一 在base class构造期间,virtual函数不是virtual函数

    class Transaction {								// 所有交易的base class
    public:
    	Transaction();
    	virtual void logTransaction() const = 0;	// 做出一份因类型不同而不同的日志记录(pure virtual)
    };
    Transaction::Transaction() {
    	...
    	logTransaction();							// 最后动作是记录这笔账
    }
    
    class BuyTransaction: public Transaction {
    public:
    	virtual void logTransaction() const;
    	...
    }
    class SellTransaction: public Transaction {
    public:
    	virtual void logTransaction() const;
    	...
    }
    
    // 创建实例
    BuyTransaction b;
    

    创建实例b的时候,会调用构造函数,又因为BuyTransaction类继承了Transaction类,所以会先调用父类的构造函数,在父类的构造函数的最后一行又调用了一个虚函数。 因为还没有调用子类的构造函数,所以此虚函数会调用父类定义的函数,而不会调用子类的函数。这里也许就跟你想要的出现了偏差。

    规则二 令derived classes 将必要的构造信息向上传递至base class构造函数

    class Transaction {
    public:
    	explicit Transaction(const std::string& logInfo);
    	void logTransaction(const std::string& logInfo) const;   // 如今是个non-virtual函数
    };
    Transaction::Transaction(const std::string& logInfo) {
    	...
    	logTransaction(logInfo);
    }
    class BuyTransaction: public Transaction {
    public:
    	BuyTransaction( parameters )
    		: Transaction(createLogString( parameters ))      // 将log信息传给base class构造函数
    		{ ... }
    	...
    private:
    	static std:: string createLogString( parameters );
    }
    

    注意 这里子类的构造函数利用了初值列的方式向父类进行传递参数。

    总结

    1. 在构造函数和析构函数期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层)
  • 相关阅读:
    SpannableString
    Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区别
    Java 之 File
    android 获取配置文件 相对路径
    Canvas
    Java Set List Map
    Comparable与Comparator区别
    HashMap HashTable ConcurrentHashMap
    centos7 mongodb 3.4 yum 安装
    对于JAVA程序优化的一些想法,读书有感.治疗强迫症良药
  • 原文地址:https://www.cnblogs.com/zhonghuasong/p/7354066.html
Copyright © 2011-2022 走看看