第9课 - 构造与析构 - 上
1. 对象的初始化
生活中存在的对象都是被初始化后才上市的,初始状态是对象普遍存在的一个状态的。一般而言所有的对象都需要一个确定的初始状态。
解决方案:
为每个类都提供一个public的initialize函数;对象创建后立即调用initialize函数进行初始化。
#include <stdio.h>
class Test
{
private:
int i;
public:
void initialize()
{
i = 0;
}
int getI()
{
return i;
}
};
int main()
{
Test t1;
Test t2;
Test t3;
t1.initialize();
t2.initialize();
t3.initialize();
printf("t1.i = %d ", t1.getI());
printf("t2.i = %d ", t2.getI());
printf("t3.i = %d ", t3.getI());
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果,各个变量的值都变成了1。
initialize只是一个普通的函数,必须显示的调用。一旦由于失误的原因,对象没有初始化,那么结果将是不确定的。没有初始化的对象,其内部成员变量的值是不定的。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
void initialize()
{
i = 0;
j = 0;
k = 0;
}
void print()
{
printf("i = %d, j = %d, k = %d ", i, j, k);
}
};
int main()
{
Test t1;
Test t2;
Test t3;
t1.print();
t2.print();
t3.print();
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果,各个变量的值不定。
2. C++中的构造函数
C++中的类可以定义与类名相同的特殊成员函数;这种与类名相同的成员函数叫做构造函数;构造函数在定义时可以有参数,但是没有任何返回类型的声明。
class Test
{
private:
int i;
int j;
int k;
public:
Test(int v)
{
i = j = k =v;
}
......
}
l 构造函数的调用
一般情况下C++编译器会自动调用构造函数,在一些情况下则需要手工调用构造函数。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
Test(int v)
{
i = v;
j = v;
k = v;
}
void print()
{
printf("i = %d, j = %d, k = %d ", i, j, k);
}
};
int main()
{
Test t1(4); //自动调用构造函数
Test t2 = 5; //自动调用构造函数
Test t3 = Test(6); //主动调用构造函数
t1.print();
t2.print();
t3.print();
Test tA[3] = {Test(1), Test(2), Test(3)}; //主动调用构造函数,不手动写会报错。
for(int i=0; i<3; i++)
{
tA[i].print();
}
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
i = 4, j = 4, k =4
i = 5, j = 5, k =5
i = 6, j = 6, k =6
i = 1, j = 1, k =1
i = 2, j = 2, k =2
i = 3, j = 3, k =3
l 成员函数的重载
类的成员函数和普通函数一样可以进行重载,并遵守相同的重载规则。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
Test()
{
i = 0;
j = 0;
k = 0;
}
Test(int v)
{
i = v;
j = v;
k = v;
}
void print()
{
printf("i = %d, j = %d, k = %d ", i, j, k);
}
void print(int v)
{
printf("v = %d ", v);
}
};
int main()
{
Test t1(4);
Test t2 = 5;
Test t3 = Test(6);
Test t4;
t4.print();
t1.print();
t2.print();
t3.print();
Test tA[3];
for(int i=0; i<3; i++)
{
tA[i].print();
}
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
i = 0; j = 0; k = 0
i = 4; j = 4; k = 4
i = 5; j = 5; k = 5
i = 6; j = 6; k = 6
i = 0; j = 0; k = 0
i = 0; j = 0; k = 0
i = 0; j = 0; k = 0
定义数组没有初始化,Test tA[3]使用了没有参数的构造函数。
3. 两个特殊的构造函数
#include <stdio.h>
/*
注意:
1. 当类中没有定义任何一个构造函数,C++编译器会为提供无参构造函数和拷贝构造函数
2. 当类中定义了任意的非拷贝构造函数时,C++编译器不会为提供无参构造函数
*/
class Test
{
public:
Test()
{
printf("Test() ");
}
Test(const Test& obj)
{
printf("Test(const Test& obj) ");
}
};
int main()
{
Test t1;
Test t2 = t1;
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
Test<>
Test<const Test& obj>
无参构造函数
当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空。
拷贝构造函数
当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值复制。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
void print()
{
printf("i = %d, j = %d, k = %d ", i, j, k);
}
};
int main()
{
Test t1;
Test t2 = t1;
t1.print();
t2.print();
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
i = 4200582, j = 2686760, k =4200678
i = 4200582, j = 2686760, k =4200678
编译器提供的复制函数,将对应函数一一赋值。
4. 写代码--创建数组类
Array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_
class Array
{
private:
int mLength;
int* mSpace;
public:
Array(int length);
Array(const Array& obj);
int length();
void setData(int index, int value);
int getData(int index);
void destory();
};
#endif
Array.cpp
#include "Array.h"
Array::Array(int length)
{
if( length < 0 )
{
length = 0;
}
mLength = length;
mSpace = new int[mLength];
}
Array::Array(const Array& obj)
{
mLength = obj.mLength;
mSpace = new int[mLength];
for(int i=0; i<mLength; i++)
{
mSpace[i] = obj.mSpace[i];
}
}
int Array::length()
{
return mLength;
}
void Array::setData(int index, int value)
{
mSpace[index] = value;
}
int Array::getData(int index)
{
return mSpace[index];
}
void Array::destory()
{
mLength = -1;
delete[] mSpace;
}
main.c
#include <stdio.h>
#include "Array.h"
int main()
{
Array a1(10);
for(int i=0; i<a1.length(); i++)
{
a1.setData(i, i);
}
for(int i=0; i<a1.length(); i++)
{
printf("Element %d: %d ", i, a1.getData(i));
}
Array a2 = a1;
for(int i=0; i<a2.length(); i++)
{
printf("Element %d: %d ", i, a2.getData(i));
}
a1.destory();
a2.destory();
printf("Press any key to continue...");
getchar();
return 0;
}
小结:
构造函数是C++中用于初始化对象状态的特殊函数。
构造函数在对象创建时自动被调用。
构造函数和普通成员函数都遵循重载规则。
拷贝构造函数是对象正确初始化的重要保证。