1. 程式人生 > >C語言到C++ 物件和類的進一步學習2

C語言到C++ 物件和類的進一步學習2

1.淺拷貝


#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
using namespace std;

class Name
{
public:
	Name(const char *myp)
	{
		len = strlen(myp);
		p = (char*)malloc(len + 1);
		strcpy(p,myp);
	}
	~Name()
	{
		if (p != NULL)
		{
			free(p);
			p = NULL;
			len = 0;
		}
	}


protected:
private:
	char *p;
	int len;
};

void objplaymain()
{
	Name obj0("zhan");
	Name obj1 = obj0; 
	//使用編譯器的預設的賦值建構函式
	//只是簡單的將成員變數賦值
	//free函式會重複釋放同一塊的記憶體 引起錯誤
	//淺拷貝

	//Name obj2("zhan");
	//obj2 = obj1;	//C++編譯器預設的 = 號也是淺拷貝

}

int main06()
{
	objplaymain();  //程式異常


	system("pause");
	return 0;
}

 

2.深拷貝


#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
using namespace std;

class NameA
{
public:
	NameA(const char *myp)
	{
		len = strlen(myp);
		p = (char*)malloc(len + 1);
		strcpy(p, myp);
	}

	//淺拷貝的解決方案 手動編寫賦值建構函式 
	//深拷貝
	NameA(const NameA &obj)
	{
		len = obj.len;
		p = (char*)malloc(len + 1);
		strcpy(p, obj.p);
	}

	~NameA()
	{
		if (p != NULL)
		{
			free(p);
			p = NULL;
			len = 0;
		}
	}
protected:
private:
	char *p;
	int len;
};

void objplaymain1()
{
	NameA obj0("zhan");
	NameA obj1 = obj0; 
}

int main07()
{
	objplaymain1();  //程式正常

	system("pause");
	return 0;
}

3.建構函式的初始化列表

 

#include <iostream>

using namespace std;


//建構函式的初始化列表 解決:在B類中組合了一個A類的物件
//根據建構函式的呼叫規則 設計A的建構函式必須要用
//新的語法規則 Constructor::Constructor():m1(v1),m2(v2),m3(v3)


class A
{
public:
	A(int _a)
	{
		a = _a;
		cout << "建構函式a:" << a << endl;
	}
	~A()
	{
		cout << "解構函式a:" << a << endl;
	}
protected:
private:
	int a;
};

class B
{
public:
	B(int _b):a1(4),a2(6)
	{
		b = _b;
	}
protected:
private:
	int b;	
	A a1;	//定義的順序
	A a2;
};
//1先執行 被組合物件的建構函式
//如果組合物件有多個 按照定義順序 而不是按照初始化列表的順序
//解構函式:和建構函式順序相反

//2被組合物件的構造順序和定義的順序有關係,與初始化列表的順序沒有關係

//在構造中呼叫建構函式 會產生一個新的匿名物件

int main08()
{
	A a1(5);
	B b1(6);
	
	system("pause");
	return 0;
}

 

4.new和delete的基礎語法

#include <iostream>

using namespace std;

// malloc  free   C語言的函式
// new     delete 操作符是C++的語法
//new可以分配 基礎型別 分配陣列變數 分配類物件

class T
{
public:
	T(int _a)
	{
		a = _a;
		cout << "建構函式執行" << endl;
	}
	~T()
	{
		cout << "解構函式執行" << endl;
	}

private:
	int a;
protected:

};


//分配基礎型別  
//malloc/new  delete/free可以混搭
int main91()
{
	//C++ int型別記憶體 初始化為100
	int *p = new int(100);	
	cout << "p:" << *p << endl;
	delete p;
	p = NULL;

	//C語言
	int *p1 = (int *)malloc(sizeof(int));
	*p1 = 100;
	cout << "p1:" << *p1 << endl;
	free(p1);	//釋放	
	p1 = NULL;

	system("pause");
	return 0;
}

//分配陣列
//malloc/new  delete/free可以混搭
int main92()
{

	//C語言分配陣列
	int *p = (int *)malloc(sizeof(int)*10);
	p[0] = 100;
	cout << "p[0]:" << p[0] << endl;
	free(p);
	p = NULL;

	//C++
	int *p1 = new int[100];
	p1[1] = 102;
	cout << "p1[1]" << p1[1] << endl;
	delete[] p1;
	p1 = NULL;

	system("pause");
	return 0;
}

//分配物件 new delete 
////malloc free 不會呼叫構造/解構函式
//new可以呼叫建構函式 delete可以呼叫解構函式
int main09()
{
	//C語言
	T * p = (T*)malloc(sizeof(T));
	free(p);

	//C++
	T *p1 = new T(10);
	//free(p1);
	delete p1;


	system("pause");
	return 0;
}

5.靜態成員變數和靜態成員函式

#include <iostream>

using namespace std;

//C++類物件中的成員變數和成員函式是分開儲存的	
//普通成員變數:儲存與物件中,與stuct變數有相同的記憶體佈局和位元組對齊方式
//靜態成員變數:儲存於全域性資料區
//成員函式: 儲存於程式碼段
//普通成員函式包含一個指向具體物件的指標,靜態成員變數不包含指向具體物件的指標
class Z
{
public:
	void printC()
	{
		cout << "C:" << c << endl;
	}
	void addC()
	{
		c++;
	}

	//靜態成員函式,只能呼叫類的靜態成員變數
	//不能使用普通成員變數 
	static void getC() 
	{
		cout << "static getC:" << c << endl;
	}

protected:
private:
	int a;
	int b;
	static int c;  //全部物件共同使用
};

int Z::c = 10;   //設定初始值

int main10()
{
	Z z1, z2, z3;

	z1.printC();
	z2.addC();
	z1.printC();

	//靜態成員函式的呼叫方法
	z3.getC();		//用物件
	Z::getC();		//用類名

	printf("Z:%d",sizeof(Z));
	system("pause");
	return 0;
}

6.this指標

#include <iostream>

using namespace std;

//this是指向自身的指標
class TT
{
public:
	TT(int a,int b)
	{
		this->a = a;
		this->b = b;
	}
	void printT()
	{
		cout << "a:" << a << endl;
		cout << "b:" << this->b << endl;
	}
private:
	int a;
	int b;

protected:
};

int main()
{
	TT t1(5,6);
	t1.printT();

	system("pause");
	return 0;
}