<!--結構體-->
ios
還記得C語言中的結構體麼?
struct Point{
double x;
double y;
};
上面的代碼是一個「結構體模版」,咱們利用它建立了一個叫作Point的類型。
在這以後,咱們就能夠像聲明基本類型的變量同樣聲明Point類型:
Point ob;
ob叫作結構體Point的一個「實例」。(更多被稱爲「對象」,下文中再也不區分「實例」和「對象」這兩個詞。)數組
而當咱們 int n; 的時候,會講聲明瞭int類型的一個「變量」 n。
安全
而當咱們Point ob; 的時候,咱們通常稱「構建了Point的一個對象」 ob。
函數
結構體是一種複合類型,可是它和一樣身爲複合類型的數組不一樣。spa
數組是相同類型元素的線性集合,而一個結構體中卻能含有不一樣類型的成員。
對象
<!--數組操做技巧--> // 這是穿插的關於數組經常使用操做的講解 和結構體與類並無多大關係 不感興趣的能夠跳過^_^
內存
char name[20];
咱們這樣就聲明瞭一個數組,而且每一個name[i](0 <=i < 20)都是一個獨立的char類型的變量。它們被稱爲數組的「元素」。
值得一提的是,同一個數組的各個元素所佔用的內存空間是連續的。ci
這使得咱們在遍歷(檢索)整個數組的時候,速度很是的快:
int line[] = {2, 5, 6, 7, 8, 12, -5, -32}; // 1
int len = sizeof(line) / sizeof(int); // 2
for(int i = 0; i < len; i++)
line[i] = -line[i];
上述語句遍歷這個數組,而且將每一個元素的值都取反。
第 1 個語句說明,數組能夠根據你聲明時填寫的數據自動分配大小,可是一旦分配,數組的大小就定了。
第 2 個語句能夠直接肯定數組中元素的個數,這樣就無需一個個數了。
sizeof是一個操做符,用法相似於函數。當參數是數組名時,將獲得整個數組所佔內存的字節數;而當參數是類型時,獲得的是該類型變量的字節數。
而對於字符串數組,初始化有更方便的方法:作用域
char name[] = "Always Laugh";字符串
這樣name就會被自動分配成長度13的數組(別忘了'\0')。
除了以前介紹的使用sizeof操做符取元素個數的方法之外,頭文件<string.h>(C++中shi<cstring>)中的strlen函數能夠更方便地取字符串長度:
char name[] = "Always Laugh";
int len = strlen(name);
for(int i = 0; i < len; i++)
name[i]++;
這個代碼會把name數組的的每一個元素在字符表中「後移」一位。
須要注意的是,strlen只能處理char的字符串數組,對int等不適用。
而且它以字符串末尾的'\0'字符爲結束標誌,所以取到的每每不是數組大小。
<!--類-->
如今介紹C++中的「類」這個概念,它和結構體極其類似。
咱們先寫一個使用結構體的程序:
#include <iostream>
using namespace std;
struct Point{ // 1 結構體的模版
double x; // 成員變量
double y;
};
int main()
{
Point p; // 2 結構體實例的構建
p.x = 3.2; // 3 結構體實例的使用
p.y = 8.9;
cout << "(" << p.x << "," << p.y << ")" << endl; // 結構體的使用
return 0;
}
結構體的模版和函數的定義性質相同(以後介紹的「類」也一樣),只是規定了這個類型的內部結構和工做原理,並不分配內存。
咱們在使用結構體對象的時候,老是使用它的成員。「.」這個操做符用來鏈接結構體的實例和它的成員。
實例的名稱能夠自由去定義,就像變量名同樣,可是同一個結構體/類的實例老是擁有徹底相同的的成員,都和模版中的一致。
即利用相同模版初始化的實例都具備相同的成員。
而當將類引入時,會發生較大的變化:
#include <iostream>
using namespace std;
class Point{ // 類模板
private:
double x; // 私有成員變量
double y; // 私有成員變量
public:
setPoint(double m, double n){ // 共有成員函數
x = m; y = n; // 私有成員變量x y 在同爲成員的函數中出現
} // 而且此時不須要"."做爲成員鏈接符 由於x y 和函數setPoint 都在Point類「內部」
printPoint(){ // 共有成員函數
cout << "(" << x << "," << y << ")" << endl; // 同上
}
};
int main()
{
Point p;
p.setPoint(3.2, 8.9);
p.printPoint();
return 0;
}
這個程序和用結構體的效果是相同的,可是複雜的地方集中在了類的模版定義部分。
出現了不少陌生的東西,private,public,甚至還有函數。
這是由於,對於類而言,不只變量能夠做爲成員,函數也能夠。
(注意:如今結構體也支持成員函數了 可是這個概念和類更緊密)
而當你想要在主函數中使用以下語句時:
p.x = 2.2; p.y = 1.1;
你會發現這個不容許的。
緣由就在於關鍵字private(私有的),它將x和y成員保護了起來,使它們在「模版區」以外不能出現。
注意是「不能出現」,而不只是「不能賦值」。這意味着 cout << p.x; 也是不容許的。
關鍵字public(公有的)定義的成員能夠暴露給外界,正如主函數中的p.setPoint(3.2, 8.9);和p.printPoint();同樣。
把x和y設置爲私有成員是爲了數據的隱祕性和安全性:
int main()
{
Point p;
p.setPoint(3.2, 8.9);
p.printPoint();
return 0;
}
這是剛剛的主函數,咱們從中根本看不出p這個類含有哪一種或者多少個私有成員,更不知道成員叫作x/y。這種技巧叫作「信息屏蔽」。
它們確實能夠在類模版中看到,可是在工程中咱們使用的類,大多數是見不到類模版的,他們存放在不一樣的文件中。
這樣,咱們只須要知道類的公有成員函數接受哪些變量,起到哪些做用,學會調用便可。至於具體細節,內部邏輯,咱們不須要知道。
這就是「封裝」,C++的三大特性之一。
正如你看到的,私有成員變量能夠在成員函數中直接出現,由於它們處於同一個做用域中(類模版的花括號)。
有私有成員函數嗎?固然有。它能夠供其餘私有成員函數或者公有成員函數去調用。
總之,只有公有成員(能夠出如今「模版區」以外)纔會和「.」連用。由於一個「實例」的聲明和使用都是在外界的。
簡而言之:
成員包括私有成員和公有成員。
成員分爲成員變量和成員函數。
<!--構造函數-->
class Point{
private:
double x;
double y;
public:
Point(){
}
Point(double m, double n) {
x = m; y = n;
}
setPoint(double m, double n){
x = m; y = n;
}
printPoint(){
cout << "(" << x << "," << y << ")" << endl;
}
};
仍然是那個類,多了兩個比較怪異的函數。沒錯,函數的名稱和類名稱同樣,而且他們不含返回值。
有了它們,咱們即可以在主函數中這樣子聲明p。
int main()
{
Point p(3.2, 8.9);
p.printPoint();
return 0;
}
構造函數是在初始化實例的過程當中調用的,這樣咱們能夠在初始化的同時給成員賦值,而setPoint用來改變成員的值。
爲何Point函數聲明瞭兩次?還記得函數重載麼?咱們重載了它。
這樣咱們既能夠在聲明實例的時候初始化它,也能夠不這麼作。
由於構造函數老是會執行的。Point p;和Point p();絲毫沒有區別。
<!--些許複雜的示例程序-->
#include <iostream>
#include <cstring>
using namespace std;
struct Friend{
char name[20];
Friend* nest;
Friend(char* pn){
strcpy(name, pn);
nest = NULL;
}
};
struct FriendList{
Friend* head;
Friend* mov;
int number;
bool none;
FriendList(Friend* pri){
head = mov = pri;
number = 1;
none = 0;
}
void ReTop(){
mov = head;
none = 0;
}
void BeFriend(Friend* someone){
Friend* temp = mov->nest;
mov->nest = someone;
someone->nest = temp;
number++;
}
bool Que(Friend *f){
if(none) {
cout << "You got no friends.\n\n";
ReTop();
return 0;
}
if(!mov->nest) none = 1;
char ch;
while(getchar() != '\n') continue;
cout << "Do you wang to make friends with "
<< mov->name << "?" << endl
<< "Y to YES and N to NO" << endl;
cin >> ch;
if(ch == 'Y') {
cout << "You've been friend with " << mov->name << "!\n\n";
BeFriend(f);
ReTop();
return 0;
}else{
mov = mov->nest;
return 1;
}
}
void End()
{
Friend* temp;
while(number--) {
temp = head->nest;
delete(head);
head = temp;
}
}
};
int main()
{
char name[20] = "Always Laugh";
Friend *Me = new Friend(name);
FriendList myFriend(Me);
int T = 4;
while(T--) {
cout << "Enter your name: ";
cin >> name;
Friend* you = new Friend(name);
cout << "Hello " << you->name << "!" << endl;
while(myFriend.Que(you));
}
return 0;
}
這個示例程序對剛接觸C++的人來講難度很大,接近一個課設。由於類的內部聯繫複雜。
而且還用到了動態內存分配(好比new和delete操做符),和鏈表的內容(這些內容對你們來講是陌生的)。
這是一個交朋友的程序,你們不妨編譯運行一下,看看效果,再盡力把代碼搞懂(爲了不越界訪問,請不要輸入得太古怪)。