嵌入式C++开发详解(三)

时间:2022-03-29 21:06:40

构造函数与析构函数(一)

一、构造函数

(1)构造函数

  ·构造函数是特殊的成员函数

  ·创建类类型的新对象,系统自动会调用构造函数

  ·构造函数是为了保证对象的每个数据成员都被正确初始化

PS:1.当没有构造函数的时候,系统会自动生成无参的构造函数

    我们一般自己加上无参构造函数,不做任何处理

  2.全局对象的构造函数先于Main函数执行

1.构造函数特点

·函数名与类名完全相同

·不能定义构造构造函数的类型(返回类型),也不能使用void,通常情况下构造

  函数应声明为公有函数,否则它不能像其他成员函数那样被显式地调用

·构造函数被声明为私有有特殊的用途

·成员对象的构造函数先于本身对象的构造函数调用

2.默认构造函数

·不带参数的构造函数

·如果程序未声明,则系统自动生成一个默认构造函数

构造函数代码示例:

Test.h
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test(int x,int y,int z);
private:
int x_;
int y_;
int z_;
};

#endif
Test.cpp
#include "Test.h"
#include <iostream>

using namespace std;

Test::Test(int x, int y, int z)
{
cout << "init Test!" << endl;
x_ = x;
y_ = y;
z_ = z;
}
main.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{
Test t(1,2,3);
return 0;
}

运行结果:

 嵌入式C++开发详解(三)

3.构造函数的重载

代码示例:

Test.h
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test();//默认的无参构造函数
Test(int x,int y,int z);
private:
int x_;
int y_;
int z_;
};

#endif
Test.cpp
#include "Test.h"
#include <iostream>

using namespace std;
Test::Test()
{
cout << "init Test2!\n" << endl;
}
Test::Test(int x, int y, int z)
{
cout << "init Test!" << endl;
x_ = x;
y_ = y;
z_ = z;
}
main.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{
Test t1;
Test t(1,2,3);
return 0;
}

运行结果:

 嵌入式C++开发详解(三)

4.构造函数与new运算符

代码示例:

Test.h
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test();//默认的无参构造函数
Test(int x,int y,int z);
private:
int x_;
int y_;
int z_;
};

#endif
Test.cpp
#include "Test.h"
#include <iostream>

using namespace std;
Test::Test()
{
cout << "init Test2!" << endl;
}
Test::Test(int x, int y, int z)
{
cout << "init Test!" << endl;
x_ = x;
y_ = y;
z_ = z;
}
main.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{
Test t1;
Test t(1,2,3);
Test *p = new Test(3,4,5);
Test array[3] = { Test(7, 8, 9) };
return 0;
}


运行结果:

 嵌入式C++开发详解(三)

5.全局对象的构造函数先于Main函数

代码示例:

Test.h:
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test(int x,int y,int z);
~Test();
private:
int x_;
int y_;
int z_;
};

#endif
Test.cpp:
#include "Test.h"
#include <iostream>

using namespace std;
Test::Test(int x, int y, int z)
{
x_ = x;
y_ = y;
z_ = z;

cout << "init Test!" << x_ << endl;
}
Test::~Test()
{
cout << "destory Test!" << x_ << endl;
}
main.c
#include <iostream>
#include "Test.h"

using namespace std;
Test t3;
int main()
{
cout << "main function!" <<endl;
Test t1(1,2,3);
Test t(4,5,6);
Test *p = new Test(7,8,9);
delete p;
return 0;
}

运行结果:

 嵌入式C++开发详解(三)

(二)转换构造函数

 ·单个参数的构造函数

 ·将其它类型转换为类类型

 ·类的构造函数只有一个参数是非常危险的,因为编译器可以使用这种构

   造函数把参数的类型隐式转换为类类型

1.初始化与赋值的区别

代码示例:

Test.h:
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test(int x);
Test();
~Test();
private:
int x_;

};

#endif
Test.cpp:
#include "Test.h"
#include <iostream>

using namespace std;
Test::Test()
{
cout << "default Test!" << endl;
}
Test::Test(int x)
{
x_ = x;

cout << "init Test!" << x_ << endl;
}
Test::~Test()
{
cout << "destory Test!" << x_ << endl;
}
msin.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{Test t = 10; //初始化
t = 20; //调用转换构造函数构建了一个临时对象
//将临时对象赋值给对象
return 0;
}


运行结果:
嵌入式C++开发详解(三)


2.转换构造函数

int main()
{ Test t = 10; //Test t(10) 初始化
t = 20; //赋值(运算符)
//调用转换构造函数构建了一个临时对象Test(20)
//将临时对象赋值给t对象
//临时对象析构
return 0;
}


部分代码示例:

Test& Test :: operator = (const Test &other)
{
if (this == &other)
{
return *this;
}
this->x_ = other.x_;

cout << "operator = !" << endl;

return * this;
}

运行结果:

 嵌入式C++开发详解(三)


3.explicit关键字  (使转换构造函数不生效)

 ·只提供给类的构造函数使用的关键字

 ·编译器不会把声明为explicit的构造函数用于隐式转换,它只能在程序代码中显示创建对象。

4.构造函数初始化列表

 ·推荐在构造函数初始化列表中进行初始化

 ·构造函数的执行分为两个阶段(初始化段、普通计算段)

 ·const成员的初始化只能在构造函数初始化列表中进行

 ·引用成员的初始化也只能在构造函数初始化列表中进行

 ·对象成员(对象所对应的类没有默认构造函数)的初始化,也只能在构造函

   数初始化列表中进行

代码示例:

class Object
{
public:
Object(int num = 0) : num_(num),kNum_(num),count(num),obj(num)
{
cout << “Object” << num_ << “...” << endl;
}
~Object()
{
cout << “~Object” << num_ << “...” << endl;
}

void DisplayKNum():num_(num),kNum_(num),count(num)
{
cout << “KNum = ” << kNum << endl;
}
private:
int num_;
int kNum_;
const int count;
object obj;//成员对象
};


5.枚举对象适用于所有对象

代码举例:

Test.h:
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
enum Result
{
success = 1,
failed = -1
};
Test(int x);
Test();
~Test();
Test& operator = (const Test &other);
private:
int x_;
const int num_;
};

#endif
Main.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{
cout << Test::success << endl;
return 0;
}


(三)拷贝构造函数

·功能:使用一个已经存在的对象来初始化一个新的同一类型的对象

·声明:只有一个参数并且参数为该类对象的引用

·如果类中没有说明拷贝构造函数,则系统自动生成一个缺省复制构造函数,

 作为该类的公有成员

1.代码示例:

Test.h:
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
enum Result
{
success = 1,
failed = -1
};
Test(int x);
Test();
~Test();
Test(const Test &other);
Test& operator = (const Test &other);
private:
int x_;
const int num_;
};

#endif
Test.cpp:
#include "Test.h"
#include <iostream>

using namespace std;
Test::Test() :num_(0)
{
cout << "default Test!" << endl;
}
Test::Test(int x) : x_(x),num_(x)
{
x_ = x;

cout << "init Test!" << x_ << endl;
}
Test::Test(const Test &other) : x_(other.x_), num_(2)
{
cout << "copy Function!" << endl;
}
Test::~Test()
{
cout << "destory Test!" << x_ << endl;
}

Test& Test :: operator = (const Test &other)
{
if (this == &other)
{
return *this;
}
this->x_ = other.x_;

cout << "operator = !" << endl;

return *this;
}
Main.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{
Test t1(5);
Test t2(t1);

return 0;
}

运行结果:

 嵌入式C++开发详解(三)

2.拷贝构造函数的调用情况

 ·用已有对象初始化对象会调用拷贝构造函数

 ·当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用

 ·当函数的返回值是类对象,函数执行完成返回调用者时使用

3.深拷贝与浅拷贝

简单理解:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝

·类中有指针成员时,一定要进行深拷贝

·=运算符必须实现深拷贝

·对于独一无二的对象禁止拷贝,将拷贝构造函数私有化。

代码示例:

String.h:
#ifndef _STRING_H_
#define _STRING_H_

class String
{
public:
String();
String(char *str);
~String();
String(const String& other);
String& operator = (const String& other);
void Display();
private:
char *str_;
};

#endif
String.cpp:
#include "String.h"
#include <iostream>

using namespace std;

String::String()
{
str_ = new char('\0');
cout << "default constrictor string!" << endl;
}

String::String(char *str)
{
cout << "constructor String" << endl;

int len = strlen(str) + 1;
str_ = new char(len);
memset(str_, 0, len);
strcpy(str_, str);
}

void String::Display()
{
cout << str_ << endl;
}

String :: ~String()
{
cout << "destory String!" << endl;

delete[] str_;
}

String::String(const String& other)
{
int len = strlen(other.str_) + 1;

str_ = new char(len);
memset(str_, 0, len);
strcpy(str_, other.str_);
}

String& String :: operator=(const String& other)
{
if (this == &other)
{
return *this;
}
int len = strlen(other.str_) + 1;
delete[] str_;
str_ = new char[len];
memset(str_, 0, len);
strcpy(str_, other.str_);
}

Main.cpp:
#include "String.h"
#include <iostream>

using namespace std;

int main()
{
String s1("hello");
s1.Display();

String s2(s1);
s2.Display();
return 0;
}


 

执行结果:

嵌入式C++开发详解(三)

4.空类默认生成的成员

class Empty{};

Empty();   //默认构造函数

Empty(const Empty&);   //默认拷贝构造函数

~Empty();     //默认析构函数

Empty& operator = (const Empty&);  //默认赋值运算符

Empty* operator&();   //取地址运算符

const Empty* operator&() const; //取地址运算符const

 

二、析构函数

(一)析构函数

·函数名和类名相似(前面多了一个字符“~”)

·没有返回类型

·没有参数

·析构函数不能被重载

·如果没有定义析构函数,编译器会自动生成一个默认析构函数,其式如下:

  类名::~默认析构名()

  {

  }

  默认析构函数是一个空函数

·默认析构函数是一个空函数

代码示例:

Test.h:
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test(int x,int y,int z);
~Test();
private:
int x_;
int y_;
int z_;
};

#endif
Test.cpp:
#include "Test.h"
#include <iostream>

using namespace std;
Test::Test(int x, int y, int z)
{
x_ = x;
y_ = y;
z_ = z;

cout << "init Test!" << x_ << endl;
}
Test::~Test()
{
cout << "destory Test!" << x_ << endl;
}
main.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{
Test t1(1,2,3);
Test t(4,5,6);
Test *p = new Test(7,8,9);
delete p;
return 0;
}

运行结果:

 嵌入式C++开发详解(三)嵌入式C++开发详解(三)

在局部对象时,构造函数调用顺序与析构函数正好相反。

1.析构函数与数组

2.析构函数与delete运算符

  析构函数在变量释放时吗,才调用,所以只有delete指针之后,才会调用析构函数

代码示例:

Test.h:
#ifndef _TEST_H_
#define _TEST_H_
class Test
{
public:
Test(int x,int y,int z);
Test();
~Test();
private:
int x_;
int y_;
int z_;
};

#endif
Test.cpp:
#include "Test.h"
#include <iostream>

using namespace std;
Test::Test()
{
cout << "default Test!" << endl;
}
Test::Test(int x, int y, int z)
{
x_ = x;
y_ = y;
z_ = z;

cout << "init Test!" << x_ << endl;
}
Test::~Test()
{
cout << "destory Test!" << x_ << endl;
}
main.c
#include <iostream>
#include "Test.h"

using namespace std;

int main()
{
Test *p = new Test[3];
delete[] p;
return 0;
}


3.析构函数显式调用