c++类大四个默认函数-构造函数 析构函数 拷贝构造函数 赋值构造函数

  每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含一个拷贝构造函数,其它的称为普通构造函数)。对于任意一个类A,如果不编写上述函数,C++编译器将自动为A 产生四个缺省的函数,例如:

  A(void);//缺省的无参数构造函数

  A(const A&a);//缺省的拷贝构造函数

  ~A();//缺省的析构函数

  A&operator=(const A &a);//缺省的赋值构造函数

1)、“缺省的拷贝构造函数”和“缺省的赋值函数”均采用“位拷贝”而非“值拷贝”的方式来实现,倘若类中含有指针变量,这两个函数注定将出错。

2)、当类还没有生成的时候,调用大是拷贝构造函数,当类已经生成的时候,调用的是赋值构造函数,如下所示:

  A a;

  A b;

  b = a;//此时类a和b都已经生成了,所以调用的是赋值构造函数

  A c;

  A d=c;//此时类d还没有生成,所以调用的是拷贝构造函数

3)、所有的函数调用传参数,调用的都是拷贝构造函数。如果函数参数用的是引用类型,则不会发生参数的拷贝,也就不会调用任何函数了。

如下:

  void print_a(const A a);//调用拷贝构造函数

  void print_b(const A &a);//为引用,不会调用任何函数

4)、拷贝构造函数和赋值构造函数对实现。

  A::A(const A&a)

  {

  }

  拷贝构造函数没有返回,为一个全新的类。

 

  A &A::operator=(const A&a)

  {

    return *this;

  }

  赋值构造函数返回自身,即*this,为在原先的类上大操作。

 

explicit:explicit构造函数是用来防止隐式转换的。

  C++提供了关键字explicit,声明为explicit的构造函数不能在隐式转换中使用

  C++中, 一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。 1、是个构造器 ,2 是个默认且隐含的类型转换操作符
所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参数构造器的参数类型, 这时候编译器就自动调用这个构造器, 创建一个AAA的对象。
这样看起来好象很酷, 很方便。 但在某些情况下(见下面权威的例子), 却违背了我们(程序员)的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
  
class Test1
{
public:
    Test1(int n)
    {
        num=n;
    }//普通构造函数
private:
    int num;
};
class Test2
{
public:
    explicit Test2(int n)
    {
        num=n;
    }//explicit(显式)构造函数
private:
    int num;
};
int main()
{
    Test1 t1=12;//隐式调用其构造函数,成功
    Test2 t2=12;//编译错误,不能隐式调用其构造函数
    Test2 t2(12);//显式调用成功
    return 0;
}
  Test1的构造函数带一个int型的参数,Test1 t1 = 12会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此Test2 t2 = 12会出现编译错误。
      普通构造函数能够被隐式调用。而explicit构造函数只能被显式调用。
posted @ 2017-03-09 10:18  任智康  阅读(1903)  评论(2编辑  收藏  举报