1. 构造函数
析构函数特点:
- 对象释放时调用
- 只能调用一次
- 用来释放内存等工作
- 析构函数总数五参的,所以不可以重载
2. 对象的new创建方法
#include <iostream>
using namespace std;
class F{
int n;
int d;
int f;
public:
F(int n = 0, int d = 1);
~F();//析构函数,自动调用。
void print(bool newLine = true);
void input();
};
//几种初始化方法
F::F(int n, int d){
F::n = n;
this->d = d;
(*this).f = 0;
}
F::~F(){
cout << "调用析构函数" << endl; }
int main(){
F* f = new F(3,3);
delete f;
f = NULL;
getchar();
return 0;
}
new创建对象的特点:
- new创建类对象需要指针接收,一处初始化,多处使用
- new创建类对象使用完需delete销毁
- new Class[4]创建的对象需要delete[] class销毁。
- new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
- new对象指针用途广泛,比如作为函数返回值、函数参数等
- 频繁调用场合并不适合new,就像new申请和释放内存一样
- 用new创建的对象可以用delete删除,同时会调用该类的析构函数,如果是用C语言风格分配的内存则不会调用析构函数
3. C++中的内存分配与释放
C++中分配动态内存推荐用new,不推荐用malloc,因为malloc是C语言的
int* a;
a = new int[7];
for(int i=0; i<7; i++){
a[i] = 100+i;
cout << a[i] << endl;
}
delete a;
a = NULL;
4. 数组形式的new类创建与delete释放(构造函数与析构函数的调用情况和数组)
#include <iostream>
#include <string>
using namespace std;
class F{
int n;
int d;
int f;
public:
F(int n = 0, int d = 1);
~F();//析构函数,自动调用。
void print(bool newLine = true);
void input();
};
//几种初始化方法
F::F(int n, int d){
F::n = n;
this->d = d;
(*this).f = 0;
cout << "调用构造函数, n = " << n << "; d = " << d <<endl;
}
F::~F(){
cout << "调用析构函数, n = " << n << "; d = " << d <<endl;
}
int main(){
cout << "F* q = static_cast<F*>(malloc(sizeof(F)));" << endl;
F* q = static_cast<F*>(malloc(sizeof(F)));
free(q);
cout << endl << endl << "F* p = new F;" << endl;
F* p = new F;
delete p;
p = NULL;
//数组形式的创建与释放
cout << endl << endl << "q = new F[4];" << endl;
q = new F[4];
for(int i=0; i<4; i++){
cout << "q[" << i << "]" << endl;
}
delete[] q;
getchar();
return 0;
}
5. 声明函数末尾加 const 的用法
1. 说明该函数对当前对象的操作是只读的
2. 函数调用时默认调用不带const的方法
3. 如果用const初始化对象会默认调用带const的方法
#include <iostream>
#include <string>
using namespace std;
class F{
int n;
int d;
int f;
public:
F(int n = 0, int d = 1);
~F();//析构函数,自动调用。
void print(bool newLine = true);
/*
此处const的说明
1. 说明该函数对当前对象的操作是只读的
2. 函数调用时默认调用不带const的方法
3. 如果用const初始化对象会默认调用带const的方法
*/
void print(bool newLine = true)const;
void input();
};
//几种初始化方法
F::F(int n, int d){
F::n = n;
this->d = d;
(*this).f = 0;
cout << "调用构造函数, n = " << n << "; d = " << d <<endl;
}
F::~F(){
cout << "调用析构函数, n = " << n << "; d = " << d <<endl;
}
int main(){
cout << "F* q = static_cast<F*>(malloc(sizeof(F)));" << endl;
F* q = static_cast<F*>(malloc(sizeof(F)));
free(q);
cout << endl << endl << "F* p = new F;" << endl;
F* p = new F;
delete p;
p = NULL;
cout << endl << endl << "q = new F[4];" << endl;
q = new F[4];
for(int i=0; i<4; i++){
cout << "q[" << i << "]" << endl;
}
delete[] q;
getchar();
return 0;
}
6. 对象在作为函数传参时的构造与析构情况
#include <iostream>
#include <string>
using namespace std;
class F{
int n;
int d;
int f;
public:
F(int n = 0, int d = 1);
F(const F& f);//如果没写编译器会自动完成
~F();//析构函数,自动调用。
void print(bool newLine = true);
void print(bool newLine = true)const;
void input();
};
//几种初始化方法
F::F(int n, int d){
F::n = n;
this->d = d;
(*this).f = 0;
cout << "调用构造函数, this = " << this << "; d = " << d <<endl;
}
F::F(const F& f){
this->n = f.n;//传参用;
this->d = f.d;
cout << "调用构造函数, this = " << this << "; d = " << d <<endl;
}
F::~F(){
cout << "调用析构函数, this = " << this << "; d = " << d <<endl;
}
F func(F f){
return f;
}
F& func2(F& f){
return f;
}
/*
结果说明:
1. 结果中会有三个析构函数,这是因为对象被创建了三次:F f(20, 50)、func(f)、return f
这三次分别是类初始化、实参-形参、return返回值
2. 为了说明被创建了三次,特意写了函数 F(const F& f);
3. 改为引用则不会有上诉问题,见 func2
*/
int main(){
F f(20, 50);
cout << "=======================================" << endl ;
func(f);
cout << "=======================================" << endl << endl ;
cout << "---------------------------------------" << endl ;
func2(f);
cout << "---------------------------------------" << endl << endl ;
getchar();
return 0;
}
7. 类似数组访问传参的可变常量问题
mutable 修饰可修改的常量
#include <iostream>
using namespace std;
class Aarray{
char a[100];
int len;
mutable int cur;
public:
void first()const{cur = -1;};
char next()const{return a[++cur];};
bool hasnext()const{return cur<=(len-1);};
void add(char c);
void add(const char* s){
while(*s){
add(*s++);
}
}
void remove(int pos);
Aarray():len(0),cur(0){};
void p(){
cout << "This is Aarray : ";
first();
while(hasnext()){
cout << next();
}
cout << endl << endl;
}
};
void Aarray::add(char c){
a[len++] = c;}
void Aarray::remove(int pos){
if (len<0 || pos>=len){
return; }
while(pos<len){
a[pos] = a[pos+1];
pos ++;
}
--len;
}
int main(){
Aarray a;
a.add("abcdefghijklmnopqrstuvwxyz");
a.p();
getchar();
return 0;
}
8. IO : >> 运算符定义
- C++中的cin 和 cout 是通过一系列的函数重载定义完成的
- 内部类似istream& operator>>(istream& cin, F& f){ cin >> n;} 的写法实现的
- 调用时候系统会先调用cin.operator>>(n);再调用operator>>(cin, n)。也就是说,当我们自己实现该方法时两个方式只实现一个即可,两个都实现会有调用问题
#include <iostream>
using namespace std;
class F{
int n;
int d;
public:
F(int n=0, int d=1):n(n),d(d){};
void print(bool newline = true);
void input();
//friend 该关键字指定类中访问私有变量
friend istream& operator>>(istream& cin, F& f);
friend ostream& operator<<(ostream& cout, const F& f);
};
//operator关键字可以定义运算符
istream& operator>>(istream& cin, F& f){
char c;
cin >> f.n >> c >> f.d;
return cin;
}
ostream& operator<<(ostream& cout, const F& f){
cout << f.n << '/' << f.d << endl;
return cout;
}
int main(){
F a,b;
cin >> a;
cout << a;
getchar();
return 0;
}
F a, b,c;
c = a+b;
//实现方法:
1. a.operator+(F b){}//看成第一个类的成员函数
2. operator(F a, F b){}//看成一个普通方法
两个实现方法