嵌入式C++開發詳解(三)
建構函式與解構函式(一)
一、建構函式
(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;
}
執行結果:
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;
}
執行結果:
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;
}
執行結果:
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;
}
執行結果:
(二)轉換建構函式
·單個引數的建構函式
·將其它型別轉換為類型別
·類的建構函式只有一個引數是非常危險的,因為編譯器可以使用這種構
造函式把引數的型別隱式轉換為類型別
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;
}
執行結果:
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_;
};
#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;
}
執行結果:
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;
}
執行結果:
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;
}
執行結果:
在區域性物件時,建構函式呼叫順序與解構函式正好相反。
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.解構函式顯式呼叫
相關文章
- 嵌入式c++軟體開發筆記第三講C++筆記
- kafka詳解三:開發Kafka應用Kafka
- 嵌入式開發該採用C++編寫嗎C++
- C++ Qt開發:Charts折線圖繪製詳解C++QT
- Java嵌入式開發講座(第三講)Java
- EasyPR--開發詳解(6)SVM開發詳解
- 純科普:什麼是嵌入式?三分鐘瞬間瞭解嵌入式系統開發
- 嵌入式Linux應用程式開發詳解教程含原始碼例子Linux原始碼
- 嵌入式c++軟體開發第四講筆記C++筆記
- C++ Qt開發:Charts繪製各類圖表詳解C++QT
- iOS 開發:『Runtime』詳解(三)Category 底層原理iOSGo
- uClinux 在 S3C4510B 嵌入式開發板上的移植和開發詳解LinuxS3
- SpringBoot詳解(三)-Spring Boot的web開發Spring BootWeb
- 【開發篇sql】 條件和表示式(三) Null詳解SQLNull
- 痞子衡嵌入式:ARM Cortex-M開發檔案詳解(3)- 工程檔案(.ewp)
- 武漢永珍奧科:嵌入式開發的三種方案!
- 詳解C++引用C++
- C++ Virtual詳解C++
- Flutter完整開發實戰詳解(三、打包與填坑篇)Flutter
- Linux嵌入式系統開發,嵌入式Linux開發教程Linux
- 嵌入式系統第三週ARM開發環境入門開發環境
- 嵌入式開發累不累?
- iOS開發之 Autolayout 詳解iOS
- 詳解JavaScript模組化開發JavaScript
- 【iOS開發】iOS 動畫詳解iOS動畫
- C++ stl容器詳解C++
- c++ vector用法詳解C++
- C++堆疊詳解C++
- C++ 字串使用詳解C++字串
- C++物件模型詳解C++物件模型
- Java 併發開發:Lock 框架詳解Java框架
- 微軟Azure區塊鏈開發工具包三大功能詳解微軟區塊鏈
- 嵌入式開發丨瞭解系統中的Uboot功能boot
- 做嵌入式開發辛苦嗎?
- 嵌入式開發基礎(3)
- 我看嵌入式開發薦
- 嵌入式CGI開發之旅——3
- 嵌入式CGI開發之旅——2