目录
析构函数
析构函数与构造函数先后对应,析构函数就是用来收尾释放内存的函数。
析构函数语法:
//面向对象
//作者:分解机226
#include <iostream>
using namespace std;
class BOLI
{
public:
BOLI(int a, int b) :a(a), b(b)
{
cout << "构造函数被调用" << endl;
}
~BOLI()
{
cout << "析构函数被调用" << endl;
}
void DB()
{
cout << "a=" << a << ",b=" << b << endl;
}
private:
int a, b;
};
int main()
{
BOLI boli(520, 1314);
boli.DB();
return 0;
}
析构函数与构造函数一样与类同名,不同的是析构函数前面加了一个波浪线,一般情况下析构函数是不会被自动调用的,这里是因为对象boli在main()函数中被创建,所以他是分配在栈上的,在主函数结束时会自动销毁。
动态分配对象内存:
我们在使用new时会调用构造函数,使用delete会调用析构函数,我们可以使用两者来动态分配内存。
//面向对象
//作者:分解机226
#include <iostream>
using namespace std;
class BOLI
{
public:
BOLI(int a, int b) :a(a), b(b)
{
cout << "构造函数被调用" << endl;
}
~BOLI()
{
cout << "析构函数被调用" << endl;
}
void DB()
{
cout << "a=" << a << ",b=" << b << endl;
}
private:
int a, b;
};
int main()
{
BOLI* d = new BOLI(520, 1314);
d->DB();
delete d;
d = new BOLI(4665, 456);
d->DB();
delete d;
return 0;
}
我们可以直观的看到,每次使用new的时候构造函数都会被调用,每次使用delete的时候析构函数都会被调用。
//面向对象
//作者:分解机226
#include <iostream>
using namespace std;
class BOLI
{
public:
BOLI(int size) :size(size)
{
arr = new int[size];
for (int i = 0; i < size; i++)
{
arr[i] = i;
}
}
~BOLI()
{
delete[] arr;
}
void d()
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << "\t";
}
cout << endl;
}
private:
int* arr;
int size;
};
int main()
{
BOLI DB(5);
DB.d();
return 0;
}
上面一段代码虽然在类的内部使用了动态内存分配,但是由于对象创建在栈上,因此析构函数会被自动调用,不i会有内存遗漏。
类的作用域
一个类的创建就确定了一块独一无二的作用域,两个类中可以声明重名的函数和变量,这是因为在大多数情况下我们都是通过类的对象来访问成员的,但是也有些例外,所以我们要掌握域操作符的用法。
作用域操作符
//面向对象
//作者:分解机226
#include <iostream>
using namespace std;
class BOLI
{
public:
BOLI()
{
}static int num;
private:
};
int BOLI::num = 2;
int num = 3;
int main()
{
cout << "BOLI::num的值是" << BOLI::num << endl;
cout << "num的值是" << num << endl;
return 0;
}
上面的一段代码使用了作用域操作符,在全局作用域中我们定义了两个num其中没有BOLI:的是普通的全局变量,有BOLI:的是类的静态成员变量,在类定义中就声明了一次。
//面向对象
//作者:分解机226
#include <iostream>
using namespace std;
class BOLI
{
public:
BOLI()
{
}
static void printBOLI()
{
cout << "print BOLI" << endl;
}
};
class DAIJIE
{
public:
DAIJIE() {}
void printBOLI()
{
BOLI::printBOLI();
}
private:
int num;
};
int main()
{
DAIJIE daijie;
daijie.printBOLI();
return 0;
}
我们使用作用域操作符可以轻易的使用另一个类的成员函数,而不存在类与类之间明显的边界,只要求我们需要访问的成员处于合法的访问权限即可。
类的静态成员
类的静态局部变量与函数的局部变量的区别在于,静态变量的生命周期是贯穿整个程序的而不是一次的函数调用,静态变量只在函数内部可见。类的静态成员分为静态成员变量和静态成员函数。
类的静态成员变量
类的静态成员变量的生命周期与类绑定,它的作用域是类,也就是在类的所有对象中都是可见的。
//面向对象
//作者:分解机226
#include <iostream>
using namespace std;
class BOLI
{
public:
BOLI(float price):price(price){}
float getprice()
{
return discountrate * price;
}
private:
float price;
static float discountrate;
};
float BOLI::discountrate = 0.85;
int main()
{
BOLI camera(2299.99);
cout << "相机的最总价格是" << camera.getprice() << endl;
BOLI tv(1199.99);
cout << "电视价格" << tv.getprice() << endl;
return 0;
}
上面的一段代码,使用静态成员变量定义了一个商品对象通用的折扣变量,只需要初始化一次,就可以在该类的实例对象的getprice()函数中使用,之后还可以改变这个值,如果我们使用一般的成员变量,这样的修改就要在所有对象中都修改一遍。静态成员变量初始化就像全局变量一样,要在全局作用域中进行。这是因为静态成员变量的生命周期是全局的,在初始化静态成员变量时要省略关键字static,还需要加一个类的限定符“BOLI::”。
类的静态成员函数
静态成员函数作用于类,而不是作用于具体对象,
//面向对象
//作者:分解机226
#include <iostream>
#include <string>
using namespace std;
class BOLI
{
public:
BOLI(int id,string name):id(id),name(name){}
static int generateID()
{
return globalID++;
}
string getname()
{
return name;
}
int getId()
{
return id;
}
private:
string name;
int id;
static int globalID;
};
int BOLI::globalID = 1;
int main()
{
BOLI boli1(BOLI::generateID(), "张三");
cout << boli1.getname() << "的学号是" << boli1.getId() << endl;
BOLI boli2(BOLI::generateID(), "历史");
cout << boli2.getname() << "的学号是" << boli2.getId() << endl;
}
在调用静态函数的时候,我们要加上类的限定符,判断一个函数是否应该设计为静态函数的依据就是,从含义上思考这个函数如果由具体的对象调用是否合理,
注意类的静态成员函数中只能访问静态成员变量和其他静态成员函数,一般的成员变量和成员函数是不能被访问的。