构造函数是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 }
运行结果如下:
通过分析运行结果我们可以发现:
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 }
运行结果如下:
分析运行结果:
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 }
运行结果如下:
分析运行结果:
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(...)
{
......
}
讲解完毕,若有不足之处,敬请指出!!!