我们先来看这样一段代码:
#include <iostream>
#include <string>
using namespace std;
class Point2D
{
public:
void init(int x,int y);
void paint();
private:
int m_x;
int m_y;
};
void Point2D::init(int x,int y)
{
m_x=x;
m_y=y;
}
void Point2D::paint()
{
cout << m_x << "," << m_y << endl;
}
int main()
{
Point2D p;
p.init(1,2);
p.paint();
return 0;
}
在这段代码中,init函数是用来初始化对象p中的点的。
在C++中为了效率,在创建对象后编译器并不会为我们清理那个对象的空间。
举个例子:我们要搬进一个房子住,编译器不会帮我们清理那个房子,他觉得我们进入房子了以后会自己清理,这样的话清理两次影响效率。但是有些OOP语言会帮我们填充这个空间。在VS下,编译器会给这里填充一个16进制的0XCD,2个0XCD连起来就刚好是国标码中的“烫”。如果在一段程序中看到“烫烫烫烫”就说明碰到了未初始化的空间。
但是,调用init()完全靠程序员的自觉性。
在C++中提供了一个初始化的函数,称为constructor function。
/*构造函数,构造器,没有返回类型,必须和类的名字一样,会在对象被创建的时候自动被调用。*/
构造函数:
- 为成员变量赋初始值,分配资源,设置对象的初始状态
- 函数名与类名相同,没有返回类型
- 对象创建时自动调用且只调用一次
栈区创建对象:对象定义语句
堆区创建对象:new操作符
- 对象创建过程
为整个对象分配内存
构造基类部分(如果存在基类)
构造成员变量
执行构造函数代码
- 一般访问属性为public,除非我们不允许外部创建对象
构造函数重载
构造函数通过参数表的差别形成重载
不同的构造函数表示对象不同的创建方式,通过构造实参类型分配
使用默认参数可以减少重载版本
默认构造函数
若一个类没有定义任何构造函数,那么编译器会提供一个公有的默认构造函数
若定义了构造函数,编译器不会再提供默认构造函数
默认构造函数一定是无参构造函数,无参构造不一定是默认构造函数
默认构造函数作用
基本类型:不做初始化
类类型:调用对应类的缺省构造函数初始化对象
初始化表
在构造函数中使用初始化表,指明类的成员变量如何初始化
类类型对象必须在初始化表中显示初始化,否则调用的是缺省构造函数来初始化
常成员变量必须在初始化表中显示初始化
参数初始化顺序与初始化表列出的变量的顺序无关,它只与成员变量在类中声明的顺序有关
/*没有参数的构造函数(编译器给的或者自己写的)叫做default constructor。构造函数有参数,析构函数没有参数。*/
析构函数:在对象被销毁的时候调用
负责对象销毁时回收对象占用资源
在析构函数中delete构造函数中new的东西
在用完对象后 delete对象 调用析构函数
class Teacher
{
private:
string m_name,m_sex,m_subject;
int m_age;
public:
//也可以给构造函数的参数赋默认值
//Teacher(string name="UNKNOW",int age=18,string sex="boy",string subject="C++")
//Teacher(string name,int age,string sex,string subject)
:m_name(name),m_sex(sex),m_age(age),m_subject(subject)
// 下面是有参构造函数
Teacher(string name,int age,string sex,string subject)
{
m_name = name;
m_age = age;
m_sex = sex;
m_subject = subject;
//如果成员变量为指针, *m_pAge
//m_pAge = new int(age); //开辟一个int堆空间,把形参age赋给堆空间
//成员指针 m_pAge指向这个堆空间
}
// 下面是无参构造函数
Teacher()
{
m_name = "NULL";
m_age = 0;
m_sex = "UNKNOW";
m_subject = "UNKNOW";
}
// 下面这个是析构函数,如果在构造函数中new了,就要在析构函数中delete掉
~Teacher(){};
//下面是两个函数
void teach()
{
cout << "teaching..." << endl;
}
void introduce()
{
cout << "I am " << m_name << "," << m_age << "," << m_sex << endl;
cout << "I teach " << m_subject << endl;
}
};
int main()
{
Teacher* Mr_hanoi = new Teacher("hanoi",18,"boy","C++"); //new了一个对象,赋了值
Mr_hanoi->introduce(); //调用这个对象的introduce函数
delete Mr_hanoi; //删除对象
Teacher Mis_li;
Mis_li.introduce();
delete Mis_li;
return 0;
}
构造析构的顺序问题:
/*
构造、析构顺序
以下程序输出:
A构造
B构造
C构造
C析构
B析构
A析构
*/
#if 0
class A
{
public:
A()
{
cout << "A构造" << endl;
}
~A()
{
cout << "A析构" << endl;
}
};
class B
{
public:
B()
{
cout << "B构造" << endl;
}
~B()
{
cout << "B析构" << endl;
}
private:
A a;
};
class C
{
public:
C()
{
cout << "C构造" << endl;
}
~C()
{
cout << "C析构" << endl;
}
private:
B b;
};
int main()
{
C* pc = new C;
delete pc;
return 0;
}