19 конструктор класса (низший)

1. Два специальных конструкторов
  - без аргументов конструктор не имеет аргументов конструктора ,     чтобы объяснить: конструктор без аргументов , кажется, очень простой, но это особенно должно существовать . Потому что мы хотим использовать класс, необходимо создать объект. Создание объектов обязательно включает в себя вызов конструктора.     Примечание: Если класс не определен , когда конструктор, компилятор предоставляется по умолчанию конструктора без аргументов, а тело функции пусты. Необходимо обратить особое внимание , когда класс не имеет конструктора, компилятор будет предоставлять или не предоставлять.   - конструктор копирования     параметра конструктора Const class_name &      (Анализ конструктора не на основе конструктора копирования: . 1, Const 2, относятся к текущему классу объектов ) до тех пор , как из таких параметров , появляется в функции конструктора, он должен это конструктор копирования вверх.
    




    Если класс не определен конструктор копирования, компилятор обеспечивает конструктор копирования, просто копирование значения переменных-членов по умолчанию.

1 #include <stdio.h>
 2  
3  класс Тест
 4  {
 5  частное :
 6      INT I;
7      INT J;
8  общественного :
 9      INT GETI ()
 10      {
 11          возврата я;
12      }
 13      INT getJ ()
 14      {
 15          возврата J;
16      }
 17      / * Тест (Const Тест & т)
 18      {
 19          г = ти;
20         J = TJ;
21      }
 22      Испытание ()
 23      {
 24      } * / 
25  };
26  
27  INT основных ()
 28  {
 29      Тест t1;
30      Тест t2 = t1;
31      
32      Е ( " t1.i =% d,% = t1.j д \ п " , t1.getI (), t1.getJ ());
33      Е ( " t2.i =% d,% = t2.j д \ п " , t2.getI (), t2.getJ ());
34      
35      возврат  0 ;
36 }

В приведенном выше примере, как только определен

Test(const Test& t)
{
       i = t.i;
       j = t.j;
}
那么Test t1;就会出错。为什么?
因为找不到一个Test()的构造函数。
问题:不是编译器会默认提供一个无参构造函数吗?
一定要注意,编译器提供默认构造函数的前提,就是类中没有构造函数,一旦拥有,编译器就不再提供。
同样,如果定义了
Test()
{

}
Test t2 = t1,也会出错。原因和上面一样。

呈现一个经典面试题,下面的这个类,它里面有什么东西?

class T

{

};

它里面至少有一个无参构造函数,是编译器提供的。

2. 拷贝构造函数的意义

-兼容C语言的初始化方式
    例如:int i =2; int j = i;
         Test t1; Test t2 = t1;
-初始化行为能够符合预期的逻辑

-浅拷贝
  拷贝后对象的物理状态相同
-深拷贝
  拷贝后对象的逻辑状态相同

编译器提供的拷贝构造函数只进行浅拷贝。

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int i;
 7     int j;
 8     int* p;
 9 public:
10     int getI()
11     {
12         return i;
13     }
14     int getJ()
15     {
16         return j;
17     }
18     int* getP()
19     {
20         return p;
21     }30     Test(int v)
31     {
32         i = 1;
33         j = 2;
34         p = new int;
35         
36         *p = v;
37     }42 };
43 
44 int main()
45 {
46     Test t1(3);
47     Test t2(t1);
48     
49     printf("t1.i = %d, t1.j = %d, *t1.p = %p\n", t1.getI(), t1.getJ(), t1.getP());
50     printf("t2.i = %d, t2.j = %d, *t2.p = %p\n", t2.getI(), t2.getJ(), t2.getP());54     
55     return 0;
56 }

上面的这个程序,编译会顺利通过。并且你会看到一个现象,t1对象的p和t2对象的p指向了同一段堆空间。你是不是想,这是肯定的啊。因为我就是用t1初始化t2,这正是我想要的结果。但是根据经验,p是在堆上生成的,当我们不用的时候,需要将其释放掉。如下面的代码所示:

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int i;
 7     int j;
 8     int* p;
 9 public:
10     int getI()
11     {
12         return i;
13     }
14     int getJ()
15     {
16         return j;
17     }
18     int* getP()
19     {
20         return p;
21     }30     Test(int v)
31     {
32         i = 1;
33         j = 2;
34         p = new int;
35         
36         *p = v;
37     }
38     void free()
39     {
40         delete p;
41     }
42 };
43 
44 int main()
45 {
46     Test t1(3);
47     Test t2(t1);
48     
49     printf("t1.i = %d, t1.j = %d, *t1.p = %p\n", t1.getI(), t1.getJ(), t1.getP());
50     printf("t2.i = %d, t2.j = %d, *t2.p = %p\n", t2.getI(), t2.getJ(), t2.getP());
51     
52     t1.free();
53     t2.free();
54     
55     return 0;
56 }

编译就会出错,因为我们释放了两次相同堆空间中的内存。t1中的p和t2中的p指向了同一段堆空间。

如何解决这个问题?

应该手工来提供一个拷贝构造函数

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int i;
 7     int j;
 8     int* p;
 9 public:
10     int getI()
11     {
12         return i;
13     }
14     int getJ()
15     {
16         return j;
17     }
18     int* getP()
19     {
20         return p;
21     }
22     Test(const Test& t)
23     {
24         i = t.i;  //首先是值的复制
25         j = t.j;
26         p = new int;
27         
28         *p = *t.p;  //p的值就不能直接复制了,需要重新到堆空间中申请。申请完之后,将t1对象中p空间中的值拿出来,放到新申请的堆空间中去。
29     }
30     Test(int v)
31     {
32         i = 1;
33         j = 2;
34         p = new int;
35         
36         *p = v;
37     }
38     void free()
39     {
40         delete p;
41     }
42 };
43 
44 int main()
45 {
46     Test t1(3);
47     Test t2(t1);
48     
49     printf("t1.i = %d, t1.j = %d, *t1.p = %p\n", t1.getI(), t1.getJ(), t1.getP());
50     printf("t2.i = %d, t2.j = %d, *t2.p = %p\n", t2.getI(), t2.getJ(), t2.getP());
51     
52     t1.free();
53     t2.free();
54     
55     return 0;
56 }

 

рекомендация

отwww.cnblogs.com/-glb/p/11795514.html
рекомендация