构造函数和析构函数¶
构造函数(相当于创建)、析构函数(相当于销毁)
创造对象的时候,数据初始化,根据需要分配内存,进行初始化操作。
对象不再需要的时候,C++自动调用析构函数,进行清理操作,释放内存。
构造函数 名称和类的名称是一样的 后面一个`()`。
析构函数 前面加一个~
。
class X
{
int i;
public:
X();//构造函数 函数名和类名一样。
~X();//析构函数
};
X::X()
{
cout << "这是构造函数" << endl;
}
X::~X()
{
cout << "这是析构函数" << endl;
}
void test()
{
{
X x;//创建对象 自动调用构造函数
}//作用域。 测试析构函数。自动销毁。C++自动调用析构函数
}
构造函数可以有参数。构造函数根据需要做成有参数或没参数。析构函数永远没有参数。
class Tree
{
int height;
public:
Tree(int initialHeight);//带参数的构造函数
~Tree();
void grow(int years);
void printsize();
};
Tree::Tree(int initialHeight)
{
height = initialHeight;
}
Tree::~Tree()
{
cout << "inside Tree destructor" << endl;
printsize();
}
void Tree::grow(int years)
{
//成长了多少年
height += years;
}
void Tree::printsize()
{
cout << "Tree height is " << height << endl;
}
void test()
{
{
Tree t(12);
t.printsize();
t.grow(4);
t.printsize();
} //作用域。结束之后调用析构函数
}
例二:
// C++的Stash 虽然是C++写的 但还是C语言的写法。没有构造函数和析构函数
struct Stash
{
int size;// 每一个是多大。存字符串的话就是最多的存多少字符。
int quantity;// 数量。一共可以保存多少个。
int next;// 已经保存了多少个。
unsigned char* storage;// 指针
// 一些操作 C++可以放到里面
// 函数是在结构里面的,所以函数定义的时候要写 结构名加::
// 这些函数也叫 这个结构的成员
void initialize(int size); //这是C语言的创建和清理,不是C++的构造和析构函数
void cleanup();
void* fetch(int index);
int add(const void* element);
int count();
// 扩大内存
void inflate(int increase);
};
这种写法不太好,使用对象的时候,需要单独写初始化,如果忘了写就麻烦。
清理也是,需要手动去写。
C++有构造和析构,则不需要,自动的。
优化:¶
Stash:
// C++的Stash 虽然是C++写的 但还是C语言的写法。没有构造函数和析构函数
struct Stash
{
int size;// 每一个是多大。存字符串的话就是最多的存多少字符。
int quantity;// 数量。一共可以保存多少个。
int next;// 已经保存了多少个。
unsigned char* storage;// 指针
// void initialize(int size); //这是C语言的创建和清理,不是C++的构造和析构函数
// void cleanup();
//构造和析构函数
Stash(int size);
~Stash();
void* fetch(int index);
int add(const void* element);
int count();
// 扩大内存
void inflate(int increase);
};
Stack栈
class Stack
{
class Link //堆栈中的每一个数据都是Link。
{
void* data;//Link中的数据
Link* next;//指针 指向下一个数据
Link(void* dat, Link* nxt);//构造函数
~Link();//析构函数
}* head;//头
public:
Stack();
~Stack();
// void initialize();//堆栈初始化
void push(void* dat);//把数据压入堆栈
void* pop();//从堆栈中拿数据,只能从一头拿 不能从中间拿。把head指向的数据拿出来,head指向下一个。
void* peak();//只看一下数据,不拿出来。
// void cleanup();
};
集合的初始化¶
一个类是一个集合,类里面有很多数据成员,类是很多数据成员的集合。
集合就是很多的数据在一起。
最简单的集合就是数组。
数组初始化了就有数据,没有初始化里面就是垃圾数据。
//数组的初始化
int a[5] = {1,2,3,4,5};
// int b[6];//没有初始化,里面就是垃圾数据
int b[6] ={0};//默认的给个0
cout << b[2] << endl;
int c[] = {1,2,3,4};//可以不指定数组的大小,C++自动的计算
/**
sizeof c 数组的大小
sizeof *c 第一个数的大小
*/
for (int i = 0; i < sizeof c / sizeof *c; i++) {
cout << c[i] << endl;
}
数组使用大括号初始化,
结构sturct也可以用大括号初始化。
struct X
{
int i;
float f;
char c;
};
//初始化
X x1 = {1,2.2,'c'};
class使用大括号初始化,必须是public。
struct默认是public。
只有没有构造函数,没有私有成员,才可以使用大括号形式初始化。
如果类class有构造函数或者有私有成员,必须调用构造函数去初始化。不能使用大括号形式。
class X
{
public://类使用大括号初始化 必须是public
int i;
float f;
char c;
};
//初始化
X x1 = {1,2.2,'c'};
//数组
X x2[3] = {{1,1.1,'a'},{2,2.2,'b'}};
class Z
{
int i,j;
public:
Z(int ii, int jj)
{
i = ii;
j = jj;
}
void print()
{
cout << "i = " << i << ", j = " << j << endl;
}
};
//调用
void test()
{
Z zz[] = {Z(1,2),Z(3,4),Z(5,6),Z(7,8)};
for (int i = 0; i < sizeof zz / sizeof *zz; i++) {
zz[i].print();
}
}
默认构造函数¶
C++类没有写构造函数,C++编译的时候会自动加上一个没有参数的构造函数。并且这个构造函数里什么都不做。也没有初始化,使用的话,里面就是垃圾数据。 一般自己写上一个构造函数。
构造函数可以写多个。参数不一样。
创建对象的两种方法¶
- 在栈里面创建对象
- 在堆里面创建对象
在堆里要用指针。内置的类型也一样。
int h = 99;//在栈里
Stack s1;//对象在栈里
int* p = new int;//在堆里
//在堆里 用指针
Stack* s2 = new Stack;//在堆里创建的对象必须使用指针。没有参数的构造函数 后面可以不写小括号。
string str1("hello");//在栈里
string* str2 = new string("hello");//在堆里
cout << str1 << "," << *str2 << endl;
堆更灵活。用多少创建多少。
栈 事先知道用多少 运行执行之后不能改变
堆比栈稍慢。
new就是在堆里。
没有参数的构造函数 后面可以不写小括号。