其实,在C++中,构造函数和析构函数并无其他的难处,在应用中只需要注意以下几点即可:
构造函数和析构函数:
构造函数引入:
在C++中,不能直接对数据成员在声明时就赋初值,必须在函数中对其赋初值,一般在构造函数中对其进行赋值。如果将类看作一个封闭的个体,那么构造函数就是作为对这个封闭的个体的对外的接口,用户可以通过它(它们)对其内部的成员进行初始化。当然,也可以是普通成员函数。
在定义对象时,如果它的数据成员没有赋初值,则其值是不可预知的,这种情况下使用对象是不安全的,有时候会带来严重的后果。所以,在使用对象之前,最好确认其成员有初值。
构造函数以及析构函数的使用:
对象初始化时构造函数地两种使用方法:
第一种:类名对象名[(实参表)]
例:
#include<iostream> #include<string> using namespace std; class Person{ private: string name; int age; public: Person(string name,int age); }; Person:Person(string name,int age){ this->name=name; this->age=age; } int main(int argc, char const *argv[]) { Person dandan("Daniel",22); return 0; } |
在这一方法中,对象的初始化是在对象创建之时,即在声明的时候就初始化了对象的成员,没有显示地调用构造函数。 |
第二种:类名 *指针变量名=new 类名[(实参)]
例:
#include<iostream> #include<string> using namespace std; class Person{ private: string name; int age; public: Person(string name,int age); }; Person:Person(string name,int age){ this->name=name; this->age=age; } int main(int argc, char const *argv[]) { Person dandan("Daniel",22); Person *dandan01=new Person("Daniel",22); return 0; } |
在这种方式中,显示地调用了构造函数。先用new运算符在内存中开辟一段内存空间,在此空间中放置了一个Person对象,并且调用了该对象的构造函数初始化了该对象。但是该对象没有名字,是一个无名对象,它的内存空间地址放在指针变量中。 |
在继承中的使用:
在继承中,当需要对基类继承而来的成员进行赋值时,必须使用成员列表赋值的方法,即:
Class 派生类类名:继承方式 基类1,继承方式基类2,…
{
Public:
类名(实参1,实参2,…,实参n):基类名1(实参列表),基类名2(实参列表),…
}
在进行基类的初始化时,是按照声明的顺序初始化的,而不是按照初始化地顺序。
在成员变量是对象时地使用:
使用方法:
Class 类名{
Private:
对象名1;
对象名2;
对象名3;
…
Public:
类名(实参1,实参2,实参3,…,实参n):对象1(实参表),对象2(实参表),…,对象n(实参表)
}
构造函数的重载
在C++中,由于对象地使用是不同的,所以又是需要对不同的成员进行初始化。当我们没有自己构造构造函数时,系统会为我们生成一个没有参数的构造函数,但一旦当我们写了自己的构造函数,那么系统将不再提供默认的无参构造函数了,所以,如果在自己定义了有参构造函数时,当需要无参构造函数就得自己对构造函数进行重载。
实例:
class Person{ private: string name; int age; public: Person(string name,int age); Person(string name); Person(int age); Person(); }; Person::Person(string name,int age){ this->name=name; this->age=age; } Person::Person(string name){ this->name=name; } Person::Person(int age){ this->age=age; } Person::Person(){ name="Daniele"; age=22; } |
带默认参数的构造函数
在构造函数中,实参是可以带默认参数的,即可以在参数声明时(必须在类内)就给参数赋初值。但是,赋初值只能时从左向右的顺序。这样做的原因是因为传递参数时,对参数赋值时是从左向右的。同时需注意,一个类只能有一个默认参数构造函数,原因是怕引起歧义。
析构函数
形式:
~类名(){ … }
析构函数的任务:在对象的生命周期结束时,释放分配对象的存储空间。
调用顺序说明
先调用构造函数,当对象生命周期结束时,调用析构函数。基本顺序如下:
基类构造函数、嵌入对象构造函数、派生类构造函数、派生类析构函数、嵌入对象析构函数、基类析构函数
注意到,析构函数的调用顺序是和构造函数的调用顺序相反的。