首页 > 代码库 > effective C++ 条款09
effective C++ 条款09
条款09 绝对不在构造和析构过程中调用virtual函数:
#include <iostream>using namespace std;class Base{public: Base() { Print(); }// virtual void Print() const = 0; //报错:pure virtual function was not defined virtual void Print() { cout<<"调用的是父类的print函数"<<endl; }};class Derived:public Base{public: Derived() { } virtual void Print() { cout<<"调用的是子类的print函数"<<endl; }};int main(){ Derived d; //输出的是调用父类的Print函数; return 0;}/*当执行 Derived d;这句代码的时候,首先会有一个Derived构造函数被调用,但首先Base构造函数一定会被更早调用;derived class 的base class 成分会在derived class自身成分被构造之前先构造好;Base构造函数的最后一行调用virtual函数:Print()函数,这是引发惊奇的起点:这时候被调用的Print()函数是Base版本的不是Derived版本的,即使目前建立的对象时Derived;bass class构造期间virtual函数绝对不会下降到derived class阶层。取而代之的是,对象的作为就像隶属base类型一样;由于base class构造函数的执行更早于derived class构造函数,当base class构造函数执行是derived class的成员变量尚未初始化。如果此期间调用的virtual函数下降至derived class阶层,要知道derived 函数必然要调用derived的成员变量,而它的成员变量还没有初始化。比上述理由更根本的原因是:在derived class 对象的base class构造期间,对象的类型是base class 而不是derived class*/
上面是原书的解释,其实我觉得可以这样解释:是virtual 虚函数指针的原因,虚函数指针直到子类对象最后被构建成功才会指向子类的虚函数表,而在父类的构造函数的时候,虚函数指针这个时候还在指向父类的虚函数表,所以调用的时候肯定是从父类虚函数表中找到Print()函数调用。
如果在父类当中需要子类的信息怎么做呢?那么就要求derived class 构造函数传递必要信息给Base构造函数:
#include <iostream>#include <string>using namespace std;class Base{public: Base(int i) { this->i = i; cout<<i<<endl; } void log() const { cout<<"一个子类被创建"<<endl; }private: int i;};class Derived : public Base{public: Derived(int j) : Base(j) //把子类的信息j 传送到父类 { }private: int j;};int main(){ Derived aa(7); aa.log(); return 0;}
总结:在构造和析构过程中不要调用virtual函数,因为这类调用从不下降至derived class。
effective C++ 条款09
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。