一.构造函数
- 在对象被创建时自动执行
- 可以有多个构造函数
调用时机:
1.对象直接定义创建--构造函数不能被显式调用(栈)
2.new
动态创建(堆)
例:定义一个账单
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class Bill{
private:
string name;
int count;
float price;
public:
Bill(string n,int c,float p){//构造函数 ,不用Init了
name = n;
count = c;
price = p;
}
string GetName(){ return name; }
int GetCount(){ return count; }
float GetPrice(){ return price; }
float GetTotal(){ return count*price; }
};
class Account{
private:
vector<Bill> bills;
public:
void Add(Bill bill){
bills.push_back(bill);//把bill尾插入bills中
}
void Print(){
cout << "name\tcount\tprice\ttotal" << endl;
cout << "-----------------------------" << endl;
float sum = 0;
for(int i=0;i<bills.size();++i){
cout << bills[i].GetName() << "\t";
cout << bills[i].GetCount() << "\t";
cout << bills[i].GetPrice() << "\t";
cout << bills[i].GetTotal() << endl;
sum += bills[i].GetTotal();
}
cout << "-----------------------------" << endl;
cout <<"Total:\t\t\t" << sum << endl;//"\t"是tab键,使对齐
}
};
int main(){
Account account;
//堆上定义:
Bill* p = new Bill("Banana",3,2.3);
account.Add(*p);
delete p;
p = NULL;
//栈上定义:
Bill a("Apple",10,2.5);//直接初始化
Bill b("Orange",5,3);
Bill c("Pair",4,3.6);
account.Add(Bill("grape",5,2.99)); //也可以直接赋值调用,匿名对象
account.Add(a);
account.Add(b);
account.Add(c);
account.Print();
}
默认构造函数:
类中没有显式的定义任何构造函数,编译器就会自动为该类型生成默认构造函数,默认构造函数没有参数。 例:最后输出为:Simple()x4
class Simple{
public:
Simple(){
cout << "Simple()" << endl;
}
};
int main(){
Simple s;
Simple arr[3];
}
例:如上一段代码,若在int main()中直接写 Bill p;则将会报错,因为已经定义过构造函数了,没有默认构造函数了。
若定义数组,则在类里写一个,默认构造函数,例:
class Bill{
public:
Bill(){
name = " ";
count = 0;
price = 0;
}
Bill(string n,int c,float p){
name = n;
count = c;
price = p;
}
};
int main(){
Bill bills[3];//会调用第一个构造函数,一次性定义三个变量
Bill a("Apple",10,2.5);//会调用第二个构造函数
}
或者,不用再写新的构造函数,初始化时写成数组形式
Bill bills[3] = {
Bill("a",1,2),
Bill("b",3,4),
Bill("c",5,6)
};
for(int i=0;i<3;i++){
account.Add(bills[i]);
}
构造函数的三个作用
- 给创建的对象建立一个标识符
- 为对象数据成员开辟内存空间
- 完成对象数据成员的初始化
初始化列表
类名(参数):成员变量(参数){
函数体
}
可以有很多成员变量
例:输出为 Simple(10) Simple(100)
class Simple{
public:
Simple(){
cout << "Simple("<< n <<")" << endl;
}
};
class SimpleWrapper{
Simple s;
public:
SimpleWrapper(int n):s(n){
// s = Simple(n);
}
};
int main(){
Simple s(10);
SimpleWrapper sw(100);
}
默认参数:
#include<iostream>
using namespace std;
class Simple{
int n;
public:
// Simple():n(0){}
Simple(int n = 0):n(n){//默认参数为0(当没写参数时),合并了默认构造函数
cout << __func__ << "(" << n << ")" <<endl; //__func__为输出函数名(Simple)
}
void Print(){
cout << __func__ << "():" << n << endl;//__func__为Print
}
};
int main(){
Simple s(10);
s.Print();
Simple* p = new Simple(20);
p->Print();
Simple s2;
Simple* p2 = new Simple;
}
当把实现和声明拆开时,实现中写int n = 0; 声明中不用写,但可以写/*=0*/来注释。
二.析构函数
作用:释放对象所申请占有的资源
当每次申请了新的内存后,要再释放,每次都delete太麻烦了,所以有了析构函数
#include<iostream>
using namespace std;
class Simple{
int* p;
public:
Simple(int n):p(new int(n)){//p为指针,申请一块内存
cout << __func__ << endl;
// p = new int(n);
}
void Print(){
cout << *p << endl;
}
~Simple(){//析构函数,在作用域最后自动调用(栈上),因为栈会自动释放内存
cout << __func__ << endl;//检验是否调用
delete p;
p = NULL;
}
};
int main(){
{
Simple s(10);
s.Print();
}
Simple* p = new Simple(20);
p->Print();
delete p;//因为内存是我们手动申请的,所以不能自动释放,调用不了析构函数
}
- 析构函数的函数名与类名相同
- 函数名前必须有一个
~
- 没有参数
- 没有返回值类型、也没有返回值
- 只能有一个析构函数
默认析构函数
类中没有显式的定义析构函数,编译器就会自动为该类型生成默认析构函数。