C++ 构造函数讲解

构造函数是C++、Java等面向对象编程语言不可绕过的话题,构造函数的作用就是初始化所创建对象的数据成员。不过与Java相比C++的构造函数显得更为复杂。因此,现在便来讲解一下C++的构造函数,以此进一步加深对构造函数的理解。

C++的构造函数分为无参构造函数和有参构造函数,且构造函数可以重载。当一个类中没有自定义的构造函数时,创建对象时便会自动调用系统默认的无参构造函数,不过这个构造函数的函数体为空,什么操作也不执行。不过一旦有自定义的构造函数时,便再也不会调用系统默认的构造函数。如果要使用无参构造函数,便需要自行定义。

 

数据成员为基本类型的类的讲解:

示例代码如下:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class Test
 5 {
 6     public:
 7         Test();
 8         Test(int a, int b);
 9     private:
10         int a;
11         int b;
12 };
13 
14 Test::Test()
15 {
16     cout << "调用Test的无参构造函数" << endl;
17     a = 5;
18     b = 10;
19 }
20 
21 Test::Test(int a, int b)
22 {
23     cout << "调用Test的有参构造函数" << endl;
24     this->a = a;
25     this->b = b;
26 }
27 
28 int main()
29 {
30     //若想通过无参构造函数初始化对象,只能以此种方式声明对象
31     Test t1;
32     Test t2(5, 10);
33     Test t3 = Test(10, 20);
34 
35     Test* t11 = new Test;
36     Test* t22 = new Test(30, 60);
37 }
View Code

运行结果如下:

     

通过分析运行结果我们可以发现:

Test t1;这个语句所执行的操作是:在栈区为对象t1分配存储空间,并调用无参构造函数对t1数据成员进行初始化。

Test* t11 = new Test;这个语句所执行的操作是:在栈区为t11指针分配存储空间,在堆区为t11所指向的对象分配存储空间,并调用默认构造函数对对象的数据成员进行初始化。

 

数据成员为类类型的类的讲解:

示例代码:

 1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 class Person
 7 {
 8     public:
 9         Person();
10         Person(string name, int age);
11         void display();
12     private:
13         string name;
14         int age;
15 };
16 
17 Person::Person()
18 {
19     cout << "调用 Person 无参构造函数" << endl;
20     name = "kkkk";
21     age = 1111;
22 }
23 
24 Person::Person(string name, int age)
25 {
26     cout << "调用 Person 有参构造函数" << endl;
27     this->name = name;
28     this->age = age;
29 }
30 
31 void Person::display()
32 {
33     cout << "Name: " << name << " Age: " << age << endl;
34 }
35 
36 class Test
37 {
38     public:
39         Test();
40         Test(string name, int age, int value);
41         void show();
42     private:
43         Person person;
44         int value;
45 };
46 
47 Test::Test()
48 {
49     person = Person("wwww", 3333);
50     person.display();
51     cout << "调用 Test 无参构造函数" << endl;
52     value = 100;
53 }
54 
55 Test::Test(string name, int age, int value):person(name, age)
56 {
57     person.display();
58     cout << "调用 Test 第二个有参构造函数" << endl;
59     value = 100;
60 }
61 
62 void Test::show()
63 {
64     person.display();
65     cout << "Value: " << value << endl;
66 }
67 
68 int main()
69 {
70     Test t1;
71     cout << "##################################" << endl;
72     Test t2("hhhh", 8888, 8);
73     return 0;
74 }
View Code

运行结果如下:

分析运行结果:

Test::Test()
{
    person = Person("wwww", 3333);
    person.display();
    cout << "调用 Test 无参构造函数" << endl;
    value = 100;
}

此构造函数实际是首先调用person的无参构造函数初始化person,然后再初始化本对象基本数据类型的数据成员。

而person = Person("wwww", 3333);语句是将Person("wwww", 3333)对象的数据成员复制给本person对象的数据成员,而且通过=复制本身也只是一种浅拷贝。相当于person对象被进行了两次初始化

 

Test::Test(string name, int age, int value):person(name, age)
{
    person.display();
    cout << "调用 Test 第二个有参构造函数" << endl;
    value = 100;
}

这个Test函数与上一个Test并无本质区别,只是这个Test函数是显式调用person对象的有参构造函数。

由此可以得出以下结论:

有类A,A有类类型数据成员B b,那么A的构造函数只能是以下形式:

如果B有无参构造函数:

A::A()

{

  ......

}

A::A(...)

{

  ......

}

如果B有有参构造函数:

A::A():b(...)

{

  .....

}

A::A(...):b(...)

{

  ......

}

 

继承时构造函数的讲解:

示例代码:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class A
 6 {
 7     public:
 8         A();
 9         A(int a);
10     private:
11         int a;
12 };
13 
14 A::A()
15 {
16     cout << "调用A无参构造函数" << endl;
17     a = 10;
18 }
19 
20 A::A(int a)
21 {
22     cout << "调用A有参构造函数" << endl;
23     this->a = a;
24 }
25 
26 class B: public A
27 {
28     public:
29         B();
30         B(int a, int b);
31     private:
32         int b;
33 };
34 
35 B::B()
36 {
37     cout << "调用B无参构造函数" << endl;
38     b = 20;
39 }
40 
41 B::B(int a, int b):A(a)
42 {
43     cout << "调用B有参构造函数" << endl;
44     this->b = b;
45 }
46 
47 int main()
48 {
49     B b1;
50     cout << "##################################" << endl;
51     B b2(50, 60);
52     return 0;
53 }
View Code

运行结果如下:

分析运行结果:

B::B()
{
    cout << "调用B无参构造函数" << endl;
    b = 20;
}

此构造函数调用了A类的无参构造函数,且首先执行A类的构造函数,后执行B类的构造函数

B::B(int a, int b):A(a)
{
    cout << "调用B有参构造函数" << endl;
    this->b = b;
}

此构造函数与上一构造函数并无本质区别,只是显示调用A类的有参构造函数

由此可以得出以下结论:

现有类A,类B,且B继承A

如果A有无参构造函数,那么B的构造函数可以这么写:

B::B()

{

   ......

}

B::B(...)

{

  ......

}

如果A有有参构造函数,那么B的构造函数可以这么写:

B::B():A(...)

{

  ......

}

B::B(...):A(...)

{

  ......

}

讲解完毕,若有不足之处,敬请指出!!!

posted @ 2014-03-28 22:01  瓦尔登湖畔的小木屋  阅读(703)  评论(0编辑  收藏  举报