嵌入式C++开发详解(三)
来源:互联网 发布:涡扇15 知乎 编辑:程序博客网 时间:2024/05/21 19:48
构造函数与析构函数(一)
一、构造函数
(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_;}; #endifTest.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;}
运行结果:
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_;}; #endifTest.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;}
运行结果:
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_;}; #endifTest.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;}
运行结果:
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_;}; #endifTest.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;}
运行结果:
(二)转换构造函数
·单个参数的构造函数
·将其它类型转换为类类型
·类的构造函数只有一个参数是非常危险的,因为编译器可以使用这种构
造函数把参数的类型隐式转换为类类型
1.初始化与赋值的区别
代码示例:
Test.h:#ifndef _TEST_H_#define _TEST_H_class Test{public:Test(int x);Test();~Test();private:int x_;};#endifTest.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;}
运行结果:
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;}
运行结果:
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_;}; #endifMain.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_;}; #endifTest.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;}
运行结果:
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_;}; #endifString.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;}
执行结果:
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_;}; #endifTest.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;}
运行结果:
在局部对象时,构造函数调用顺序与析构函数正好相反。
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_;}; #endifTest.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.析构函数显式调用
- 嵌入式C语言实战开发详解(三)
- 嵌入式C++开发详解(三)
- 嵌入式C学习笔记(三)嵌入式开发选择C语言的原因
- 嵌入式C语言实战开发详解(一)
- 嵌入式C语言实战开发详解(二)
- 嵌入式C语言实战开发详解(四)
- 嵌入式C语言实战开发详解(一)
- 嵌入式驱动开发的前期Linux 和 C学习(三)
- 嵌入式开发的那些事儿(三)
- 华为笔试-嵌入式开发(三)
- 嵌入式linux开发环境搭建(三)
- 嵌入式Linux C语言开发工具—编译器gcc详解
- 嵌入式C++开发详解(一)
- 嵌入式C++实战开发详解(一)
- 嵌入式C++开发详解(二)
- 嵌入式C++开发详解(四)
- 嵌入式C++开发详解(五)
- 嵌入式C++开发详解(六)
- LeetCode 79. Word Search
- ckeditor自定义视频插件支持优酷、土豆、腾讯视频
- AJAX - $.post(url,data,function,type)
- centOS 安装Redis
- spark Streaming 和drools整合
- 嵌入式C++开发详解(三)
- oc-内存管理 - 探路篇
- NoSQl基本介绍
- HTML滚动文字代码 marquee标签
- 解决MySQL不能插入中文
- Java生成缩略图Thumbnailator(转载)
- 名胜古迹扎堆的河北文博园(定州文博园)
- JSTL标签和EL表达式以及Strust2标签和ognl表达式
- winform TreeView树节点上下移动