• 注册
  • 关于作者
    企业认证:趣记站长
    关注 6 粉丝 4 喜欢 9 内容 992
    江西省·南昌市
    聊天 送礼
    • 查看作者
    • C++箴言:避免析构函数调用虚函数

        如果你已经从另外一种语言如C#或者Java转向了C++,你会觉得,避免在类的构造函数或者析构函数中调用虚函数这一原则有点违背直觉。但是在C++中,违反这个原则会给你带来难以预料的后果和无尽的烦恼。

        正文

        我想以重复本文的主题开篇:不要在类的构造或者析构函数中调用虚函数,因为这种调用不会如你所愿,即使成功一点,最后还会使你沮丧不已。如果你以前是一个Java或者C#程序员,请密切注意本节的内容-这正是C++与其它语言的大区别之一。

        假设你有一个为股票交易建模的类层次结构,例如买单,卖单,等等。为该类交易建立审计系统是非常重要的,这样的话,每当创建一个交易对象,在审计登录项上就生成一个适当的入口项。这看上去不失为一种解决该问题的合理方法:

        

        class Transaction {// 所有交易的基类

        public:

         Transaction();

         virtual void logTransaction() const = 0;//建立依赖于具体交易类型的登录项

         ...

        };

        Transaction::Transaction() //实现基类的构造函数

        {

         ...

         logTransaction(); //最后,

      C++箴言:理解inline化的介入和排除
      C语言编程程序的内存如何布局,C语言编写linux下的守护进程,在C++中创建持久对象,C++中类的数据成员的安全隐患,经典c程序100例(91--100),经典c程序100例(81--90),经典c程序100例(71--80),经典c程序100例(61--70),经典c程序100例(51--60),经典c程序100例(41--50),经典c程序100例(31--40),经典c程序100例(21--30),经典c程序100例(11--20),经典c程序100例(1--10),实例解析C++/CLI的串行化,用C语言编写Windows服务程序的五个步骤,自定义类_string类,关于拷贝构造函数和赋值运算符,用c语言演绎“生命游戏”,c语言中时间陷阱的实现
      C/C++

      登录该交易

        }

        class BuyTransaction: public Transaction {

        // 派生类

        public:

         virtual void logTransaction() const; //怎样实现这种类型交易的登录?

         ...

        };

        class SellTransaction: public Transaction {

        //派生类

        public:

         virtual void logTransaction() const; //怎样实现这种类型交易的登录?

         ...

        };

        现在,请分析执行下列代码调用时所发生的事情:

        BuyTransaction b;

        很明显,一个BuyTransaction类构造器被调用。但是,首先调用的是Transaction类的构造器-派生类对象的基类部分是在派生类部分之前被构造的。Transaction构造器的最后一行调用了虚函数logTransaction,但是奇怪的事情正是在此发生的。被调用函数logTransaction的版本是Transaction中的那个,而不是BuyTransaction中的那个-即使现在产生的对象的类型是BuyTransaction,情况也是如此。在基类的构造过程中,虚函数调用从不会被传递到派生类中。代之的是,派生类对象表现出来的行为好象其本身就是基类型。不规范地说,在基类的构造过程中,虚函数并没有被"构造"。

        对上面这种看上去有点违背直觉的行为可以用一个理由来解释-因为基类构造器是在派生类之前执行的,所以在基类构造器运行的时候派生类的数据成员还没有被初始化。如果在基类的构造过程中对虚函数的调用传递到了派生类,派生类对象当然可以参照引用局部的数据成员,但是这些数据成员其时尚未被初始化。这将会导致无休止的未定义行为和彻夜的代码调试。沿类层次往下调用尚未初始化的对象的某些部分本来就是危险的,所以C++干脆不让你这样做。 

      C程式中关于整数储存的说明
      C语言编程程序的内存如何布局,C语言编写linux下的守护进程,在C++中创建持久对象,C++中类的数据成员的安全隐患,经典c程序100例(91--100),经典c程序100例(81--90),经典c程序100例(71--80),经典c程序100例(61--70),经典c程序100例(51--60),经典c程序100例(41--50),经典c程序100例(31--40),经典c程序100例(21--30),经典c程序100例(11--20),经典c程序100例(1--10),实例解析C++/CLI的串行化,用C语言编写Windows服务程序的五个步骤,自定义类_string类,关于拷贝构造函数和赋值运算符,用c语言演绎“生命游戏”,c语言中时间陷阱的实现
      C/C++

    • 0
    • 0
    • 0
    • 62
    • 单栏布局 侧栏位置: