c++构造函数的显式和隐式调用

如果在编写类时没有显示的写出其构造函数,析构函数,以及重载赋值操作符,编译器会在编译代码时,会为该类加上这些。

其形式大致如下:

A(){}

A& operator =(const A& a)
{
    // 这个地方可能有点不当,只是为了表明这是一个浅拷贝
    memcpy(this, &a, sizeof(A));
    return *this;
}

A(const A& a)
{
   // 这儿调用了赋值重载函数
   *this = a;
}

 // 注意在析构函数前不会加上virtual关键字
 ~A(){}

下面给出一些示例,注释部分说明了函数调用的情况:

void f()
{
   // A()构造函数被调用
   A a;
   // A(const A& a)构造函数被调用
   A b(a);
   // A(const A& a)构造函数被调用
   A c = a;
   // A& operator = (const A& a)赋值操作符重载函数被调用
   b = c;
}
// 离开f()函数之前,a,b,c的析构函数被调用,做一些清理工作

“A c = a;”

这句代码实际调用的是拷贝构造函数,而非赋值函数。

因此,我们可以构造出这样的代码。

class A
{
 private:
    int *m_data;
    std::string ss;
 public:
    A()
    {
        m_data = NULL;
    }
    A(int n)
    {
        m_data = NULL;
        if (n>0)
            m_data = new int[n];
    }
    A& operator =(const A& a)
    {
        memcpy(this, &a, sizeof(A));
        return *this;
    }
    virtual ~A()
    {
        if (NULL!=m_data)
        {
            delete [] m_data;
            m_data = NULL;
        }
    }
};


 int main(int argc, char* argv[])
{
    // 将整数3赋值给一个对象
     A a = 3;    
    return 0;
}

将整数3赋值给一个A类型对象a,然而以上代码可以编译通过。 -- 有点不合常理

这是由于“单参数构造函数”被自动类型转换(这是一个隐式转换)。

可以通过explicit关键字 ,阻止“以赋值语法进行带有转型操作的初始化”。如下所示:

class A
{
 private:
    int *m_data;
    std::string ss;
 public:
    A()
    {
        m_data = NULL;
    }
    explicit A(int n)
    {
        m_data = NULL;
        if (n>0)
            m_data = new int[n];
    }
    A& operator =(const A& a)
    {
        memcpy(this, &a, sizeof(A));
        return *this;
    }
    virtual ~A()
    {
        if (NULL!=m_data)
        {
            delete [] m_data;
            m_data = NULL;
        }
    }
};


 int main(int argc, char* argv[])
{
    // A a = 3; // 编译无法通过
     A b(3);     // 可以编译通过
    
    return 0;
}

 

你可能感兴趣的:(C/C++,c++,构造函数的显式和隐式调用)