effective c++绝不在构造和析构过程中调用virtual函数

不应该在构造函数和析构函数期间调用virtual函数

class Transaction
{
public:
    Transaction()
    {
        init();
    }
    void init()
    {
        logTransaction();
    }
    virtual void logTransaction() = 0;
};
class BuyTransaction: public Transaction
{
    void logTransaction(){}
};
int main()
{
    BuyTransaction b;

}

运行时错误
在derived class对象的base class构造期间,对象类型是base class而不是derived class

不只是virtual函数会被编译器解析至base class,若使用运行期类型信息,也会把对象视为base class 类型

同样对于析构函数,一旦derived class析构函数开始执行,derived class成员变量便呈现未定义值,C++视他们仿佛不存在,进入base class析构函数后对象便成为一个base class对象

看到了一些关于explicit的介绍,感觉挺好的

class String {
public:

    String ( int n )
    {
        cout << " 我分配了 " << endl;
    }; //本意是预先分配n个字节给字符串
    String ( const char* p )
    {

    }; // 用C风格的字符串p作为初始化值
};
int main()
{
    String s4 = 10; //编译通过,也是分配10个字节的空字符串
    String s5 = 'a'; //编译通过,分配int(‘a’)个字节的空字符串
}

下面的s5赋值容易造成歧义,到底是调用第一个构造函数,还是第二个(其实都是调用第一个)

摘抄了一些别人博客的explicit的介绍:
C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有”显式”那么必然就有”隐式”,那么什么是显示而什么又是隐式的呢?

如果c++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,如下面所示:

class MyClass  
{  
public:  
    MyClass( int num );  
}  
//.  
MyClass obj = 10; //ok,convert int to MyClass 

在上面的代码中编译器自动将整型转换为MyClass类对象,实际上等同于下面的操作:

MyClass temp(10);  
MyClass obj = temp; 

上面的所有的C++ explicit关键字相关的操作即是所谓的”隐式转换”。

如果要避免这种自动转换的功能,我们该怎么做呢?嘿嘿这就是关键字explicit的作用了,将类的构造函数声明为”显式”,也就是在声明构造函数的时候前面添加上explicit即可,这样就可以防止这种自动的转换操作,如果我们修改上面的MyClass类的构造函数为显式的,那么下面的代码就不能够编译通过了,如下所示:

class MyClass  
{  
public:  
explicit MyClass( int num );  
}  
//.  
MyClass obj = 10; //err,can't non-explict convert 

C++ explicit关键字应用方法详解
C++笔记(1)explicit构造函数

曾经在effective c++看到过要用explicit构造函数,但是都忘了,不光忘了规则,连explicit构造函数的作用都忘了,更囧的是,我竟然还写过关于要用explicit关键字的博客

如果搁以前,我一定会埋怨自己,觉得记忆力不行,但是现在的我,并不是以前的我啦,因为我以前只是记住这件事情,并不知道为什么,只是生硬的记忆,现在算是稍微理解为什么了。。。

以后学习也是,没学习一个知识,多花点时间问一下,为什么会是这样,虽然貌似浪费了一点时间,但是可能这个知识就被终身记住了,节约了一大笔时间(不过这不包括考试前突击)

为解决这个问题,也就是需要在base class构造函数中调用virtual函数(其实就是调用derived class的信息),可以通过derived class向base class中传递信息

class Transaction
{
public:
    explicit Transaction(string logInfo)
    {
        logTransaction(logInfo);
    }
    void logTransaction(string logInfo){}
};
class BuyTransaction: public Transaction
{
 public:
      BuyTransaction(string para)
        : Transaction(createLogString(para))
      {

      }
 private:
    static string createLogString(string para){}
};

这里面private static函数 createLogString的运用非常好,保证构造函数调用前就可以使用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值