c++隨記一(黑馬程序員學習筆記)

1、當結構體作爲參數直接輸入函數中時,如果結構體過於大,則全部再複製一次開銷也十分大,一般使用地址傳參。如果怕被不小心更改,則在參數前加入const修飾。

2、常量指針 const int * p =&a
指針指向可以更改,但值不可更改。
指針常量 int * const p =&a
指針指向不可更改,但值可以更改。

3、無論什麼類型的指針,32位系統下佔4個字節,64位系統下佔8個字節。

4、內存分爲代碼區、全局區、棧區和堆區。其中,代碼區作用是存放二進制的代碼由操作系統進行管理;全局區存放全局變量和靜態變量,同時還包含了常量區,包括字符串常量和const修飾的全局常量,在程序結束後由操作系統釋放;棧區存放局部變量,參數,由編譯器自動釋放,注意,不要返回局部變量的地址;堆區由程序員申請釋放,程序結束時也會釋放,一般用new來申請。

5、引用即起一個別名。如int &b = a。引用必須初始化,且引用在初始化後,不可以改變。引用傳遞函數參數時,形參也會修飾實參。引用函數返回值時,不要返回局部變量的引用,函數調用可以作爲左值。C++內部引用本質就是指針常量.

6、如果函數有一個變量有了默認參數,那麼這個默認參數往後都必須有默認參數。函數聲明與函數實現裏面只能有一個有默認參數。函數佔位參數,如int aaaa(int),佔位參數也可以有默認參數,如int aaaa(int = 10)。

7、函數重載(函數名相同)。滿足條件:作用域相同,但函數參數不同或參數類型不同或順序不同。返回值不能作爲重載的條件(如void XXX和int XXX)。引用可以重載,const添加與不添加是兩個不同的參數類型

8、C++封裝繼承多態。struct默認權限是Public,而class默認權限是私有。m設置成員屬性私有可以自己控制讀寫,也可以檢查數據的有效性。

9、構造函數和析構函數。用於初始化和清理。構造函數有參數,可以發生重載,而析構函數沒有參數,不能重載。構造和析構如果自己不提供,編譯器會自動空實現一個。構造函數可以分爲無參構造和有參構造,或者分爲普通構造和拷貝構造Person(const Person &p)。調用默認構造函數的時候,後面不要跟括號,直接Person p,否則編譯器會把它當作函數聲明。匿名對象,如Person(10),當前行結束後系統會回收。不要用拷貝構造函數初始化匿名對象,編譯器會認爲是重定義。
調用構造函數三種方法:

//1、括號法
Person p1;//默認構造函數
Person p2(10);//有參構造函數
Person p3(p2);//拷貝構造函數
//2、顯示法
Person p1;
Person p2 = Person(10);
Person p3 = Person(p2);
//3、隱式轉換法
Person p4 = 10//與上面P2相同,有參構造
Person p5 = p4;

10、拷貝構造函數調用時機
(1)使用一個已經構造完畢的對象來初始化一個新的對象。(2)值傳遞的方式給函數參數傳值。(3)以值方式返回局部對象(return p)。

11、構造函數調用規則。創建一個類編譯器默認添加默認構造、析構函數、拷貝構造(值拷貝)。

12、淺拷貝:簡單拷貝;深拷貝:堆區重新申請空間再進行拷貝。爲了防止堆區內存重複釋放,因此出現深拷貝。

13、靜態成員函數只能訪問靜態成員變量,因爲非靜態成員變量無法區分究竟是哪個對象的。靜態成員函數:所有程序共享同一個函數。靜態成員函數也是有訪問權限的。

14、成員變量和成員函數是分開存儲的。空對象所佔的內存空間爲1。因爲C++編譯器給空對象一個字節的空間,爲了區分空對象佔內存的位置。非靜態成員變量,屬於類的對象上,靜態成員變量不屬於類的對象上。非靜態成員函數和靜態成員函數也不屬於類的對象上。

15、this指針。(1)解決名稱衝突。

class Person//這裏就會導致編譯器無法區分age
{
public:
    Person(int age)
    {age = age;}
    int age
}
class Person//this指針指向的是被調用的成員函數所屬對象
{
public:
    Person(int age)
    {this->age = age;}
    int age
}

(2)返回對象本身用*this

class Person
{
public:
    Person & PersonAddPerson(Person p)
    {
       this->age += p.age;
       return *this;
    }
}

16、空指針可以調用成員函數,但不能調用有this的函數,如果有this可以前面加個if判斷指針若爲空則直接返回。

17、this指針是指針常量,指向不可修改。const修飾成員函數格式是 void 函數名() const。在成員函數名後面加const,本質是讓this指針指向的值也不能修改。但可以在變量前加關鍵字mutable後在常函數中仍然可以修改。

18、常對象是在對象前加const。但mutable也可修改。常對象只能調用常函數。

19、友元的目的是讓一個函數或者類訪問另一個類中的私有成員。三種實現方法:全局函數做友元,類做友元,成員函數做友元。全局函數做友元只需要在類中添加聲明,聲明前添加friend。類做友元,只需要在類中添加friend class XXX;成員函數做友元friend void 類名::函數名();

20、類外實現成員函數

Building::Building()
{
   m_sittingRoom = "客廳";
}

21、對於內置的數據類型的表達式的運算符是不可能改變的。

#include<iostream>
using namespace std;
//加號運算符重載
class Person
{
public:
	//1、成員函數重載
	/*Person operator+(Person& p)
	{
		Person temp;
		temp.m_A = this->m_A + p.m_A;
		temp.m_B = this->m_B + p.m_B;
		return temp;
	}*/
public:
	int m_A;
	int m_B;
};
//2、全局函數重載
Person operator+(Person& p1, Person& p2)
{
	Person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}
Person operator+(Person& p1, int val)
{
	Person temp;
	temp.m_A = p1.m_A + val;
	temp.m_B = p1.m_B + val;
	return temp;
}
void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;
	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;
	//全局函數本質調用
	//Person p3 = operator+(p1, p2);
	//成員函數本質調用
	//Person p3 = p1.operator+(p2);
	Person p3 = p1 + p2;
	//運算符重載也可以發生函數重載
	Person p4 = p3 + 10;
	cout << "p4.m_A = " << p4.m_A << endl;
	cout << "p4.m_B = " << p4.m_B << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

22、左移運算符重載使其可以輸出自定義的數據類型。但通常不會利用成員函數來實現左移的重載,因爲無法實現cout在左側。

//只能利用全局函數重載左移運算符
ostream &operator<<(ostream &cout, Person &p)
{
	cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
	return cout;
}

函數名稱前面加引用符號“&”,代表該函數返回值類型是引用。如:int &operate+(…);

23、賦值運算符重載,是因爲如果類中有堆區指針,在進行系統賦值時是淺拷貝,如果調用析構函數會造成重複釋放。因此重載賦值運算符。首先先將原本存在的堆區釋放乾淨,再重新分配一塊內存。如果想要連續賦值,需要return *this,函數類型用Person&,引用保證不是值傳遞。

#include<iostream>
using namespace std;

class Person
{
public:
	Person(int age)
	{
		m_Age = new int(age);
	}
	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}
	//重載 賦值運算符
	Person& operator=(Person& p)
	{
		//先判斷是否有屬性在堆區,如果有先釋放乾淨再深拷貝
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
		m_Age = new int(*p.m_Age);
		//返回對象本身
		return *this;
	}
	int* m_Age;
};
void test01()
{
	Person p1(18);
	Person p2(20);
	Person p3(30);

	p3 = p2 = p1;
	cout << "p1的年齡爲:" << *p1.m_Age << endl;
	cout << "p2的年齡爲:" << *p2.m_Age << endl;
	cout << "p3的年齡爲:" << *p3.m_Age << endl;
}
int main()
{
	test01();
	return 0;
}

24、函數調用運算符重載(仿函數),即重載()。其中還有匿名函數對象。

#include<iostream>
#include<string.h>
using namespace std;

class MyPrint
{
public:
	void operator()(string test)
	{
		cout << test << endl;
	}
};
void test01()
{
	MyPrint myPrint;
	//使用起來非常像函數調用,因此成爲仿函數
	myPrint("hello world");
}
//仿函數非常靈活,沒有固定寫法
class MyAdd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};
void test02()
{
	MyAdd myAdd;
	int ret = myAdd(100, 100);
	cout << "ret = " << ret << endl;
	//匿名函數對象
	cout << MyAdd()(100, 100) << endl;
}
int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章