1. 程式人生 > >複習C++基礎知識-----“我的第一本C++”讀書筆記1

複習C++基礎知識-----“我的第一本C++”讀書筆記1

Debug : 在單獨執行時,往往需要編譯器提供一些庫檔案

Release : 可以在沒有安裝visual c++的computer上正常執行

常規設定

1)
在共享DLL中使用MFC : 表示把程式中用到的MFC類庫作為動態連結庫,這樣編譯生成器的程式比較小,但是在執行的時候,需要作業系統提供額外的動態庫支援。

2)
在靜態庫中使用MFC : 表示把用到的MFC類的內容作為靜態庫加到程式中,這樣編譯產生的程式可以在任何Windwos環境下執行,但是程式的體積比較大。

3)
使用標準Windows庫 : 表示不適用MFC類庫,僅使用標準的Windows類庫。


#define and const
巨集的使用是在預處理的時候進行五條件的替換,並沒有明確指定這個常量的資料型別、所以帶來便利的同時也容易帶來問題。
所以出現了const


列舉的使用---------------------------------

enum Weekday
{
	mon,
	tue,
	wed,
	thu,
	fri,
	sat,
	sun
};


列舉預設的值是0,如果不想用預設,可以直接賦值
列舉定義之後,不能再修改其中某個元素的值


使用位操作符---------------------------------------------------

	cout << "use transpose operator :" << endl;
	int iValue = 1;
//	iValue = iValue * 4;
	iValue = iValue << 34; // 34 % 32 = 2左移 因為超過了int的大小空間
	cout << "iValue value is : " << iValue << endl;

行內函數 :
可以更形象地稱為內嵌函式,它是C++對函式的一種特殊修飾。當編譯器編譯程式時,如果發現某段程式碼在呼叫一個行內函數,它就不再去呼叫該函式,而是將該函式的程式碼整段插入當前函式呼叫的位置。這樣就省去了函式呼叫的過程,提高了程式碼的執行效率。關鍵字inline


函式過載 :
1)函式過載的意義在於可以根據輸入引數的型別或者個數,自動地在多個過載函式中查詢與之匹配的過載函式,從而只能地決定採用哪個函式版本。
2)只有相互之間的引數型別或者個數不同,才可以構成合法的過載函式


函式的宣告----也稱為函式的介面
1)試一試在純c中使用介面------------------------------------------------
2)儘量在函式中使用斷言assert判斷函式的有效性
3)函式的功能要做到單一----如果一個函式需要完成多項任務,最好拆分成多個函式


面向物件的知識 :
1)封裝
在傳統的結構化程式設計思想中,資料和演算法是相互分離的。
在面向物件的程式設計思想中,物件就是封裝資料和操作這些資料的演算法的邏輯實體,也是現實世界中物體在程式中的反映,使用封裝有的時候可以很好的保護物件的私有部分

2)繼承
從父親那裡得到技能,自己又可以繼續學習。比如我現在就站在前人的基礎上學習的c++

3)多型
就是指物件在不同情況下具有不同形式的能力。多型機制使具有不同內部結構的物件可以共享相同的外部介面。比如,給別人一幅畫,不一定是你自己畫的,也可以直接把你老爸的畫送出

想想 : 如何在面向物件程式設計思想上,考慮擴充套件、複用、可維護問題


new :
在new不成功是,不必去判斷指標是否為null,因為new不成功時,系統會自動丟擲std::bad_alloc異常,new操作永遠不會返回null


拷貝建構函式 :
預設也會有拷貝建構函式,當類中含有指標型別的屬性時,以拷貝記憶體形式出現的預設拷貝建構函式只能複製指標屬性的值,而不能複製指標屬性所指向的記憶體,在這個情況下需要自定義類的拷貝函式,完成指標屬性等需要頁數處理的屬性的拷貝工作。

p163 拷貝建構函式

namespace Zeng
{
	class CTest_A
	{
	public:
		CTest_A( int iValue, char* cName )
		{
			this->m_iValue = iValue;
			this->m_pName = new char[ strlen( cName ) + 1 ];
			strcpy( m_pName, cName );
		}
		// 拷貝建構函式
		CTest_A( const CTest_A& rCG )
		{
			this->m_iValue = rCG.m_iValue;
			this->m_pName = new char[ strlen( rCG.m_pName ) + 1 ];
			strcpy( m_pName, rCG.m_pName );
		}
		void print()
		{
			cout << "CTest_G m_iValue value is : " << this->m_iValue << endl; 
			cout << "CTest_G m_pName value is : " << this->m_pName << endl; 
			cout << "CTest_G m_pName address is : " << *this->m_pName << endl; 
		}
	public:
		int m_iValue;
		char* m_pName;
	}; // 試試拷貝建構函式
}

int _tmain(int argc, _TCHAR* argv[])
{
	Zeng::CTest_A CA( 10, "Zengraoli" );
	Zeng::CTest_A CA2( 10, "Zengraoli" );
	Zeng::CTest_A CA3( CG );
	cout << "CA print" << endl;
	CA.print();

	cout << "\n";
	cout << "CA2 print" << endl;
	CA2.print();

	cout << "\n";
	cout << "CA3 print" << endl;
	CA3.print();
	cout << "class CTest_A size is : " << sizeof( Zeng::CTest_A ) << endl;

	return 0;
}

P166 操作符過載
函式過載和操作符過載-------------------------------------

#include "stdafx.h"
#include "iostream"
using namespace std;

namespace Zeng
{
	class CTest_A
	{
	public:
		CTest_A()
		{
		}
		void print()
		{
			cout << "this is CTest_A print()" << endl;
		}
	}; // 佔1個位元組的大小

	class CTest_B : virtual CTest_A
	{
	public:
		CTest_B( int iValue ) : m_iValue( iValue )
		{
		}
		void print()
		{
			cout << "m_iValue value is : " << m_iValue << endl;
		}
	private:
		int m_iValue;
	}; // 佔8個位元組的大小

	class CTest_C : virtual CTest_A
	{
	public:
		CTest_C()
		{
		}
	}; // 佔4個位元組的大小

	class CTest_D : virtual CTest_B
	{
	public:
		CTest_D( int iValue ) : CTest_B( iValue )
		{
			this->m_iValue = iValue + 89;
		}
		void print()
		{
			cout << "m_iValue value is : " << this->m_iValue << endl;
		}
	private:
		int m_iValue;
	}; // 佔16個位元組的大小

	class CTest_E : public CTest_A
	{
	public:
		CTest_E( int iValue )
		{
			this->m_iValue = iValue + 89;
		}
		void print()
		{
			cout << "this is CTest_E not parameter's print()" << endl;
		}
		void print( int iValue )
		{
			cout << "this is CTest_E has parameter's print()" << endl;
		}
/*
		int print( int iValue )
		{
			cout << "this is CTest_E has parameter's print()" << endl;
			return 0;
		} // c++可以忽略函式的返回值,所以只能靠引數不同來進行函式過載
*/
	private:
		int m_iValue;
	}; // 試試函式過載

	class CTest_F
	{
	public:
		CTest_F( int iValue )
		{
			this->m_iValue = iValue;
		}
		void print()
		{
			cout << "CTest_F m_iValue value is : " << this->m_iValue << endl; 
		}
		const CTest_F& operator+ ( const CTest_F& rCF )
		{
			this->m_iValue += rCF.m_iValue;
			return *this;
		}
		const CTest_F& operator= ( const CTest_F& rCF )
		{
			this->m_iValue = rCF.m_iValue;
			return *this;
		}
	public:
		int m_iValue;
	}; // 試試操作符過載
}

int _tmain(int argc, _TCHAR* argv[])
{
	Zeng::CTest_A CA;
	CA.print();
	cout << "class CTest_A size is : " << sizeof( Zeng::CTest_A ) << endl;
	cout << "class CTest_B size is : " << sizeof( Zeng::CTest_B ) << endl;
	cout << "class CTest_C size is : " << sizeof( Zeng::CTest_C ) << endl;

	cout << "\n";
	Zeng::CTest_D CD( 10 );
	CD.print();
	cout << "class CTest_D size is : " << sizeof( Zeng::CTest_D ) << endl;

	cout << "\n";
	Zeng::CTest_E CE( 10 );
	CE.print();
	CE.print(1);
	cout << "class CTest_E size is : " << sizeof( Zeng::CTest_E ) << endl;

	cout << "\n";
	Zeng::CTest_F CF( 10 );
	Zeng::CTest_F CF2( 89 );
	CF = CF + CF2;
	cout << "in class CTest_F override add after : " << sizeof( Zeng::CTest_F ) << endl;
	CF.print();
	CF = CF2;
	cout << "in class CTest_F override equal after : " << sizeof( Zeng::CTest_F ) << endl;
	CF.print();
	cout << "class CTest_F size is : " << sizeof( Zeng::CTest_F ) << endl;

	return 0;
}


建構函式私有化的含義---------------------------------------------

namespace Rao
{
	class CTest
	{
	public:
		static CTest* makeAnObject()
		{
			 // 程式結束的時候 自動釋放
			static CTest instance;
			return &instance;
		}
		~CTest()
		{
			cout << "CTest Destructor...." << endl;
		}
		static int m_nValue;
	private:
		CTest()
		{
			m_nValue++;
			cout << "CTest Constructor...." << endl;
		}
		
		CTest( const CTest& CopyCTest )
		{
			m_nValue++;
			cout << "CopyCTest Constructor...." << endl;
		}

		const  CTest& operator= ( const CTest& );
	};
}
main:
	int Rao::CTest::m_nValue;

	cout << "\n";
	cout << "use Constructor privatization :" << endl;
	Rao::CTest* RaoCTest = Rao::CTest::makeAnObject();
	cout << "m_nValue :" << Rao::CTest::m_nValue << endl;
	Rao::CTest* RaoCTest2 = Rao::CTest::makeAnObject();
	cout << "m_nValue :" << Rao::CTest::m_nValue << endl;

	// 呼叫拷貝建構函式
	Rao::CTest sg = *Rao::CTest::makeAnObject();
	cout << "m_nValue :" << Rao::CTest::m_nValue << endl;

類的成員訪問控制
public : 公有訪問介面
protected : 1)可以供類自身訪問的成員 2)可以供下級子類訪問的成員
private : 僅供類自身訪問的成員


友元函式
簡單理解為 : 由於類成員的訪問控制機制,很好地實現了資料的隱藏與封裝,類的成員變數一般定義為私有成員,成員函式一般定義為公有成員,以此來提供類與外界間的通訊介面;但有特殊的情況,比如需要定義某個函式/某個類,這個函式/類不是類CA的一部分,但又需要頻繁地訪問類CA的隱藏資訊,所以C++提供了一個"friend"關鍵字來完成這個任務。
友元函式和友元類都需要試一試--------------------------------------P172
但需要記住的一點 :
1)友元關係不能被繼承。這一點很好理解,我們跟某個類是朋友,並不表示我們跟這個類的兒子(派生類)同樣是朋友。
2)友元關係是單向的,不具有交換性。

#include "stdafx.h"
#include "iostream"
using namespace std;

namespace Zeng
{
	class CTest_A
	{
	public:
		CTest_A( int iValue )
		{
			this->m_iValue = iValue;
		}
		void print()
		{
			cout << "CTest_A's m_iValue current value is : " << this->m_iValue << endl;
		}
		friend void firendFunction( const CTest_A& CA );
		friend class CTest_B;
	private:
		int m_iValue;
	};

	class CTest_B
	{
	public:
		CTest_B()
		{
		}
		void print( const CTest_A& CA )
		{
			cout << "this's firend class CTest_B print : " << CA.m_iValue << endl;
		}
	private:
	}; // 友元類

	void firendFunction( const CTest_A& CA )
	{
		cout << "this's firend function print : " << CA.m_iValue << endl;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	Zeng::CTest_A CA( 100 );
	firendFunction( CA );

	cout << "\n";
	Zeng::CTest_B CB;
	CB.print( CA );

	return 0;
}