1. 程式人生 > 實用技巧 >【C++學習教程08】函式

【C++學習教程08】函式

目錄

參考

  • 範磊C++(第十課時)
  • VS2015

筆記

普通函式的過載

普通函式可以過載

成員函式的過載

成員函式也可以被過載

函式的預設引數

  • 函式引數的初始化操作。叫預設引數又叫預設(shen)引數。
  • 若在呼叫時沒有傳遞值時,則會使用預設值。
  • 成員函式也可以有預設值。
  • 過載函式建議增加預設值?

過載建構函式

  • 建構函式可以過載但是隻能執行一個

成員變數的初始化

  • 建構函式體中進行初始化;
  • 在建構函式的函式頭進行初始化;

成員變數的初始化與建構函式

  • 構造成員和析構成員的順序(第二節課件損壞)
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
	A(int a, int b) { num = a; total = b; }//但是常量和引用不能被賦值!!
private:
	int num;
	int total;
};

int main(int argc, const char * argv[]) {

	return 0;
}

建構函式和NEW運算子

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
	A() { cout << "建構函式執行完畢" << endl; }
	void set(int a, int b)
	{
		i = a;
		j = b;
	}
	void print() { cout << i << endl; cout << j << endl; }
private:
	int i;
	char j;
};

int main(int argc, const char * argv[]) {
	A *a = new A;//在堆中建立物件
	a->set(3, 5);//指標要用成員指標運算子 //ascii碼5對應的字元
	a->print();
	system("pause");
	return 0;
}

再談預設的建構函式

  • 當不定義建構函式時,C++將預設定義一個不帶引數的建構函式。
  • 當你創造建構函式之後,編譯器就不會再提供預設建構函式。
  • 不加訪問修飾符的會預設為私有的。

複製建構函式

  • 複製建構函式可以複製一個物件
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
	A() { cout << "建構函式執行完畢" << endl; }
	A(A& one) { this->n = one.n; m = one.m; }
	//複製建構函式,引數為類A物件的一個引用,可以通過引數來接受A的引數,one就是一個別名
	//每一個類都有,不定義編譯器會自動定義,實現成員的對拷貝
	A(int i, int j) { n = i; m = j; }//帶引數的建構函式
	void print()
	{
		cout << n << m;
	}
private:
	int n;
	int m;
};

int main(int argc, const char * argv[]) {
	A a(2, 4);
	a.print();
	cout << "\n" << endl;
	A b(a);//傳遞物件會呼叫複製建構函式 //將成員進行拷貝
	b.print();
	system("pause");
	return 0;
}

解構函式和delete運算子

  • 解構函式和delete的搭配使用
  • delete會自動呼叫解構函式來釋放new運算子所建立的記憶體空間。

預設解構函式

-不定義的話,編譯器會預設定義解構函式。

呼叫建構函式進行型別轉換

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
	explicit A(int x) { i = x; cout << "建構函式執行完畢" << i<<endl; }//關閉這種特性,來制止隱式轉化
	~A(){ cout << "解構函式在執行" <<i<< endl; }
	void get() { cout << i << endl; }
private:
	int i;
};

int main(int argc, const char * argv[]) {
	A a(99);
	a.get();
	//a = 1000;//隱式轉化
	a = A(1000);//數值賦給物件 //型別轉換 //這是在呼叫建構函式 //相當於建立了臨時物件
				//引數個數和建構函式的個數一樣
	//但是這樣會導致一些意外,所以應該關閉這種特性,但是顯示轉換是可以的。
	//呼叫建構函式建立臨時物件,將臨時物件的成員i賦值給a的成員i,建立了臨時物件,所以會呼叫解構函式。
	a.get();
	system("pause");
	return 0;
}

輸出結果:

淺層複製建構函式


如果發生了delete操作,則會觸發程式崩潰。

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
	A() { x = new int; *x = 5; }
	~A() { delete x; x = NULL; }//C++區分大小寫
	A(const A&a) { cout << "複製建構函式執行" << endl;
	x = a.x;
	}
	void print() { cout << *x << endl; }
	void set(int i) { *x = i; }
private:
	int *x;
};

int main(int argc, const char * argv[]) {
	A *a = new A();
	cout << "a:";
	a->print();
	A b = (*a);//將一個物件複製給另一個物件,這時候會呼叫複製建構函式
	b.print();
	a->set(32);//a和b的x指向同一塊記憶體
	cout << "a:";
	a->print();
	cout << "b:";
	b.print();
	//delete a;//此時會報錯,
	system("pause");
	return 0;
}

輸出結果:

第二課時失效

深層複製建構函式

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
class A
{
public:
	A() { x = new int; *x = 5; }
	~A() { delete x; x = NULL; }
	//深層複製建構函式
	A(const A&a) 
	{ 
		cout << "複製建構函式執行" << endl;
		x=new int;//用複製建構函式建立的新物件的指標成員x來指向它。//兩個物件的x指標指向不同的記憶體
		*x = *(a.x);//不再複製指標而是複製指標的值
	}
	void print() const { cout << *x << endl; }
	void set(int i) { *x = i; }
private:
	int *x;
};

int main(int argc, const char * argv[]) {
	A *a = new A();
	cout << "a:";
	a->print();
	A b = (*a);//將一個物件複製給另一個物件,這時候會呼叫複製建構函式
	b.print();
	a->set(32);
	cout << "a:";
	a->print();
	cout << "b:";
	b.print();
	delete a;
	//a->print();
	b.print();
	system("pause");
	return 0;
}


輸出結果: