C++隐式构造与显式构造

<一> 

class Stock
{
private:
    string _company;
    long _share;
    double  _val;
};

C++提供了两种使用构造函数来初始化对象的方法。第一种是显式的调用构造函数:

Stock food = Stock("hello",12,20.5);

这将food对象的_company成员设置为字符串"hello",将_share成员设置为12,以此类推。

另一种是隐式地调用构造函数:

Stock garment("world",13,2.5);

这种调用更紧凑,它与下面的显示调用等价:

Stock garment = Stock("world",13,2.5);

每次创建类对象(甚至使用new动态分配内存)时,C++都使用类构造函数。下面是将构造函数与new一起使用的方法:

Stock *pstock =  new Stock("google",15,22.5);

这条语句创建了一个Stock对象,将其初始化为参数提供的值,并将该对象的地址赋给pstock指针。在这种情况下,对象没有名称,但是可以使用指针来管理该对象。

构造函数的使用不同于其他类方法。一般来说,使用对象来调用方法:

stock1.show();

但无法使用对象来调用构造函数,因为在构造函数构造出对象之前,对象是不存在的。因此构造函数被用来创建对象,而不能同过对象来调用。

<二>

class A
{
};

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

其形式大致如下:

class A
{
     A()
     {
     }

     A& operator =(const A& a)
     {
        memcpy(this, &a, sizeof(A));  //此处可能用问题,仅为表明不是浅拷贝
        return *this;
     }

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

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


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

void f()
{
 
   A a;     // A()构造函数被调用
   A b(a);  // A(const A& a)构造函数被调用 
   A c = a; // A(const A& a)构造函数被调用 
   b = c;   // A& operator = (const A& a)赋值操作符重载函数被调用 
}
 // 离开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()
{
     A a = 3; // 将整数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()
{
     // A a = 3; // 编译无法通过
     A b(3); // 可以编译通过
     return 0;
}

猜你喜欢

转载自blog.csdn.net/ox0080/article/details/84141043