第八章 C++编程之构造函数
8.1 什么是构造函数
简单说,构造函数就是在定义某个类的时候会调用的一个函数,默认构造不带参,其余构造函数可以自己实现。
8.2 示例代码—以动物为例
1、定义类的头文件(animal.h)
//以动物为例,实现无参构造和带参构造
#include <iostream>
using namespace std;
class Animal{
private:
char*name;
int age;
public:
Animal(){cout << "this is empty animal" << endl;}//无参构造
Animal(char *name,int age);//带参构造
Animal(char *name);//带参构造
void setName(char *name);
void setAge(int age);
void printInfo();
};
2、类的实现函数(animal.cpp)
#include "animal.h"
void Animal::setName(char *name)
{
this->name = name;
}
void Animal::setAge(int age)
{
this->age = age;
}
void Animal::printInfo()
{
cout << "this is " << this->name << ",age = " << this->age << endl;
}
Animal::Animal(char *name,int age)
{
cout << "Animal(char *name,int age)" << endl;
this->name = name;
this->age = age;
}
Animal::Animal(char *name)
{
cout << "Animal(char *name) " << endl;
this->name = name;
this->age = 0;
}
3、主函数(main.cpp)
#include "animal.h"
int main(int argc ,char**argv)
{
//使用普通的定义方法:若是有多个变量,每个变量重复初始化是麻烦的
Animal dog[3];//定义的时候会调用默认构造3次
dog[0].setName("dog:wangcai");
dog[0].setAge(0);
dog[0].printInfo();
dog[0].setName("dog:kangkang");
dog[0].setAge(1);
dog[0].printInfo();
dog[0].setName("dog:xxxx");
dog[0].setAge(2);
dog[0].printInfo();
Animal cat("cat",1);//调用带参构造
cat.printInfo();
Animal pig("pig");
pig.printInfo();
Animal*tiger = new Animal("tiger:laohu",2);
tiger->printInfo();
// Animal duck();//若是这种情况,相当于:int func(),即这是一个函数声明
Animal duck;//若想调用无参构造,应该使用这种方式
return 0;
}
4、Makefile文件
#生成可执行文件person,依赖于文件 main.c和person.c
# 符号的意义: $@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件
main:main.o animal.o
g++ -o $@ $^
%.o : %.cpp
g++ -c -o $@ $<
clean:
rm -rf *.o main
8.3 构造函数的调用过程
构造函数在定义时会被调用,若无实现则调用默认构造,带参时具体调用的哪个构造有类的实际构造函数决定。
8.4 对象指针、指针数组和释放指针空间
8.4.1 分配单个对象指针和释放
1、分配单个指针、使用并释放
#include "animal.h"
int main(int argc ,char**argv)
{
//1、分配一个对象指针
Animal *pig = new Animal();//默认构造
pig->setName("zhuzhu");
Animal *dog = new Animal("dog:wangcai",10);//带参构造
dog->printInfo();
delete pig;//此处会调用析构函数
delete dog;
}
2、在animal.h中增加析构函数,修改后如下
//以动物为例,实现无参构造和带参构造
#include <iostream>
using namespace std;
class Animal{
private:
char*name;
int age;
public:
Animal(){cout << "this is empty animal" << endl;}//构造函数1
Animal(char *name,int age);//构造函数2
Animal(char *name);//构造函数3
Animal(char *name,int age,int num);//构造函数4
~Animal(){//这是析构函数
cout << this->name << "out" << endl;
cout << "this is ~Animal()" << endl;
}
void setName(char *name);
void setAge(int age);
void printInfo();
};
小结:
1、分配指针对象时(new)调用对应的构造函数
2、删除指针对象时(delete)调用对应的析构函数
8.4.2 分配对象指针数组和释放
1、分配对象指针数组
#include "animal.h"
int main(int argc ,char**argv)
{
//方式1
Animal *lion = new Animal[3];
cout<< "------------------" <<endl;
lion[0].setName("shizi");
lion[0].printInfo();
cout<< "------------------" <<endl;
//方式2
Animal *tiger = new Animal[2];
tiger->setName("laohu_1");//初始化数组对象1
tiger->printInfo();
tiger[1].setName("laohu_2");
tiger[1].printInfo();
//释放指针数组空间的时候,数组成员有几个就会自动释放几个
delete []lion;//指针需要主动释放,否则会导致内存泄漏
delete []tiger;
}
2、在构造函数中申请空间,那么就在析构函数中释放空间
修改animal.h:
//以动物为例,实现无参构造和带参构造
#include <iostream>
using namespace std;
class Animal{
private:
char*name;
int age;
public:
Animal(){
name = NULL;
cout << "this is empty animal" << endl;}
Animal(char *name,int age);
Animal(char *name);
Animal(char *name,int age,int num);
~Animal();
void setName(char *name);
void setAge(int age);
void printInfo();
};
修改animal.cpp:
#include "animal.h"
#include <string.h>
#include <unistd.h>
void Animal::setName(char *name)
{
if(this->name){
delete this->name;
}
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
}
void Animal::setAge(int age)
{
this->age = age;
}
void Animal::printInfo()
{
cout << "this is " << this->name << ",age = " << this->age << endl;
}
Animal::Animal(char *name,int age)
{
cout << "Animal(char *name,int age)" << endl;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
}
Animal::Animal(char *name)
{
cout << "Animal(char *name) " << endl;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = 0;
}
Animal::Animal(char *name,int age,int num)
{
cout << "Animal(char *name,int age)" << endl;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
cout << "number is "<< num << endl;
}
Animal::~Animal()
{
// cout << "~Animal()" << endl;
if(this->name){
delete this->name;
cout << "-------~Animal()---------"<< this->name << endl;
}
}
8.5 小结
析构和构造是C++的重要函数,使用过程比较灵活,需要多积累使用方法。
1、分配指针对象时(new)调用对应的构造函数;
2、删除指针对象时(delete)调用对应的析构函数;
3、函数执行结束后,临时变量被销毁时,会自动调用析构函数,但是指针变量申请了空间不会自动调用析构函数,所以需要手动进行释放。