要想寫一個(gè)稍微大一點(diǎn)項(xiàng)目,以下知識(shí)需要繼續(xù)鞏固一下,再次回到基礎(chǔ)知識(shí)哈。
1. 頭文件
頭文件或.h文件允許將相關(guān)的函數(shù),方法和類聲明收集在一個(gè)位置。然后可以將相應(yīng)的定義放置在.cpp文件中。編譯器認(rèn)為頭聲明是一個(gè)“承諾”,該定義將在后面代碼找到。因此,如果編譯器尚未找到定義的函數(shù),則可以繼續(xù)進(jìn)行編譯,直到找到定義為止。這允許以任意順序定義(和聲明)函數(shù)。
2. 引用
#include <iostream>
using std::cout;
int main()
{
int i = 1;
// Declare a reference to i.
int& j = i;
cout << "The value of j is: " << j << "\n";
// Change the value of i.
i = 5;
cout << "The value of i is changed to: " << i << "\n";
cout << "The value of j is now: " << j << "\n";
// Change the value of the reference.
// Since reference is just another name for the variable,
// th
j = 7;
cout << "The value of j is now: " << j << "\n";
cout << "The value of i is changed to: " << i << "\n";
}

3.指針
C ++指針只是一個(gè)變量,用于存儲(chǔ)程序中對(duì)象的內(nèi)存地址。
#include <iostream>
using std::cout;
int main() {
int i = 5;
int j = 6;
// Print the memory addresses of i and j
cout << "The address of i is: " << &i << "\n";
cout << "The address of j is: " << &j << "\n";
}

可能想知道為什么同一個(gè)符號(hào)既可以用來(lái)訪問(wèn)內(nèi)存地址,也可以像以前看到的那樣,將引用傳遞到函數(shù)中:
1.符號(hào)&和*有不同的含義,這取決于它們出現(xiàn)在等式的哪一邊。
2.記住這一點(diǎn)非常重要。對(duì)于&,如果它出現(xiàn)在等式的左側(cè)(例如,聲明變量時(shí)),則表示該變量聲明為引用。如果&出現(xiàn)在等式的右側(cè),或在先前定義的變量之前,則用于返回內(nèi)存地址,如上面的示例所示。
#include <iostream>
using std::cout;
int main()
{
int i = 5;
// A pointer pointer_to_i is declared and initialized to the address of i.
int* pointer_to_i = &i;
// Print the memory addresses of i and j
cout << "The address of i is: " << &i << "\n";
cout << "The variable pointer_to_i is: " << pointer_to_i << "\n";
}
從代碼中可以看到,變量pointer_to_i使用*符號(hào)聲明為指向int的指針,pointer_to_i設(shè)置為i的地址。從打印輸出中可以看出,pointer_to_i的值與i的地址相同。

一旦有了指針,您可能需要檢索它所指向的對(duì)象。在這種情況下,*符號(hào)可以再次使用。然而,這一次,它將出現(xiàn)在一個(gè)方程的右邊或一個(gè)已經(jīng)定義的變量的前面,所以含義是不同的。在這種情況下,它被稱為“解引用運(yùn)算符”,并返回被指向的對(duì)象。您可以在下面的代碼中看到這是如何工作的:
#include <iostream>
using std::cout;
int main()
{
int i = 5;
// A pointer pointer_to_i is declared and initialized to the address of i.
int* pointer_to_i = &i;
// Print the memory addresses of i and j
cout << "The address of i is: " << &i << "\n";
cout << "The variable pointer_to_i is: " << pointer_to_i << "\n";
cout << "The value of the variable pointed to by pointer_to_i is: " << *pointer_to_i << "\n";
}

4.引用與指針
指針和引用可以在C++中使用類似的用例。如前所述,引用和指針都可以在對(duì)函數(shù)的按次傳遞引用中使用。此外,它們都提供了一種訪問(wèn)現(xiàn)有變量的可選方法:指針通過(guò)變量的地址,以及通過(guò)該變量的另一個(gè)名稱引用。但是兩者有什么區(qū)別,什么時(shí)候應(yīng)該使用它們呢?下面的列表總結(jié)了指針和引用之間的一些差異,以及應(yīng)該在何時(shí)使用它們:
引用:
引用在聲明時(shí)必須初始化。這意味著引用將始終指向有意分配給它的數(shù)據(jù)。
指針:
指針可以在不初始化的情況下聲明。如果錯(cuò)誤地發(fā)生這種情況,指針可能指向內(nèi)存中的任意地址,與該地址關(guān)聯(lián)的數(shù)據(jù)可能毫無(wú)意義,從而導(dǎo)致未定義的行為和難以解決的錯(cuò)誤。
引用:
引用不能為空。這意味著引用應(yīng)該指向程序中有意義的數(shù)據(jù)。
指針:
指針可以為空。事實(shí)上,如果指針沒(méi)有立即初始化,通常最好將其初始化為nullptr,這是一種表示指針為空的特殊類型。
引用:
當(dāng)在用于按引用傳遞的函數(shù)中使用時(shí),該引用可以作為相同類型的變量使用。
指針:
在用于按引用傳遞的函數(shù)中使用時(shí),必須取消對(duì)指針的引用才能訪問(wèn)基礎(chǔ)對(duì)象。
引用通常比指針更簡(jiǎn)單和安全。作為一個(gè)很好的經(jīng)驗(yàn)法則,在可能的情況下,應(yīng)該使用引用來(lái)代替指針。
但是,有時(shí)不能使用引用。一個(gè)例子是對(duì)象初始化。您可能希望一個(gè)對(duì)象存儲(chǔ)對(duì)另一個(gè)對(duì)象的引用。
但是,如果在創(chuàng)建第一個(gè)對(duì)象時(shí)另一個(gè)對(duì)象尚不可用,則第一個(gè)對(duì)象將需要使用指針,而不是引用,因?yàn)橐貌荒転榭?只能在創(chuàng)建另一個(gè)對(duì)象后初始化引用。
5.
#include <iostream>
#include <string>
using std::string;
using std::cout;
int main()
{
// Variables to hold each car's color.
string car_1_color = "green";
string car_2_color = "red";
string car_3_color = "blue";
// Variables to hold each car's initial position.
int car_1_distance = 0;
int car_2_distance = 0;
int car_3_distance = 0;
// Increment car_1's position by 1.
car_1_distance++;
// Print out the position and color of each car.
cout << "The distance that the " << car_1_color << " car 1 has traveled is: " << car_1_distance << "\n";
cout << "The distance that the " << car_2_color << " car 2 has traveled is: " << car_2_distance << "\n";
cout << "The distance that the " << car_3_color << " car 3 has traveled is: " << car_3_distance << "\n";
}
這適用于程序中定義的少數(shù)汽車,但是如果您希望程序跟蹤許多汽車,這將非常麻煩。你需要為每輛車創(chuàng)建一個(gè)新的變量,代碼會(huì)很快變得混亂。解決這個(gè)問(wèn)題的一種方法是定義一個(gè)Car類,將這些變量作為屬性,同時(shí)使用一些類方法來(lái)增加行駛距離并打印出汽車數(shù)據(jù)。
#include <iostream>
#include <string>
using std::string;
using std::cout;
// The Car class
class Car {
public:
// Method to print data.
void PrintCarData()
{
cout << "The distance that the " << color << " car " << number << " has traveled is: " << distance << "\n";
}
// Method to increment the distance travelled.
void IncrementDistance()
{
distance++;
}
// Class/object attributes
string color;
int distance = 0;
int number;
};
int main()
{
// Create class instances for each car.
Car car_1, car_2, car_3;
// Set each instance's color.
car_1.color = "green";
car_2.color = "red";
car_3.color = "blue";
// Set each instance's number.
car_1.number = 1;
car_2.number = 2;
car_3.number = 3;
// Increment car_1's position by 1.
car_1.IncrementDistance();
// Print out the position and color of each car.
car_1.PrintCarData();
car_2.PrintCarData();
car_3.PrintCarData();
}

這看起來(lái)沒(méi)問(wèn)題,而且已經(jīng)減少了main中的變量數(shù)量,所以可能會(huì)看到在未來(lái)如何更有條理。然而,現(xiàn)在的代碼比開(kāi)始時(shí)多得多,而且main似乎沒(méi)有組織得多。上面的代碼仍然在創(chuàng)建汽車之后為每輛汽車設(shè)置屬性。
添加一個(gè)構(gòu)造函數(shù)
解決這個(gè)問(wèn)題的最好方法是向Car類添加構(gòu)造函數(shù)。構(gòu)造函數(shù)允許您使用所需的數(shù)據(jù)實(shí)例化新對(duì)象。在下一個(gè)代碼單元中,我們?yōu)镃ar添加了一個(gè)構(gòu)造函數(shù),它允許傳入數(shù)字和顏色。這意味著可以用這些變量創(chuàng)建每個(gè)Car對(duì)象。
#include <iostream>
#include <string>
using std::string;
using std::cout;
class Car {
public:
void PrintCarData()
{
cout << "The distance that the " << color << " car " << number << " has traveled is: " << distance << "\n";
}
void IncrementDistance()
{
distance++;
}
// Adding a constructor here:
Car(string c, int n)
{
// Setting the class attributes with
// The values passed into the constructor.
color = c;
number = n;
}
string color;
int distance = 0;
int number;
};
int main()
{
// Create class instances for each car.
Car car_1 = Car("green", 1);
Car car_2 = Car("red", 2);
Car car_3 = Car("blue", 3);
// Increment car_1's position by 1.
car_1.IncrementDistance();
// Print out the position and color of each car.
car_1.PrintCarData();
car_2.PrintCarData();
car_3.PrintCarData();
}
如果計(jì)劃構(gòu)建一個(gè)更大的程序,那么此時(shí)最好將類定義和函數(shù)聲明放在一個(gè)單獨(dú)的文件中。正如我們之前討論的頭文件一樣,將類定義放在單獨(dú)的頭中有助于組織代碼,并防止在定義類之前嘗試使用類對(duì)象出現(xiàn)問(wèn)題。
- 當(dāng)類方法在類之外定義時(shí),必須使用scope resolution操作符::來(lái)指示該方法屬于哪個(gè)類。例如,在PrintCarData方法的定義中可以看到:
void Car::PrintCarData()
如果有兩個(gè)類的方法具有相同的名稱,這可以防止任何編譯器問(wèn)題。
- 改變了構(gòu)造函數(shù)初始化變量的方式。而不是以前的構(gòu)造函數(shù):
Car(string c, int n) {
color = c;
number = n;
}
構(gòu)造函數(shù)現(xiàn)在使用初始值列表:
Car(string c, int n) : color(c), number(n) {}
類成員在構(gòu)造函數(shù)的主體(現(xiàn)在是空的)之前初始化。初始化器列表是在構(gòu)造函數(shù)中初始化許多類屬性的快速方法。此外,編譯器處理列表中初始化的屬性與在構(gòu)造函數(shù)體中初始化的屬性略有不同。如果類屬性是引用,則必須使用初始值設(shè)定項(xiàng)列表對(duì)其進(jìn)行初始化。
- 不需要在類外部可見(jiàn)的變量設(shè)置為private。這意味著不能在類之外訪問(wèn)它們,這可以防止它們被意外更改。
聲明位于.h文件中,定義位于.cpp中
#ifndef CAR_H
#define CAR_H
#include <string>
using std::string;
using std::cout;
class Car {
public:
void PrintCarData();
void IncrementDistance();
// Using a constructor list in the constructor:
Car(string c, int n) : color(c), number(n) {}
// The variables do not need to be accessed outside of
// functions from this class, so we can set them to private.
private:
string color;
int distance = 0;
int number;
};
#endif
#include <iostream>
#include "car.h"
// Method definitions for the Car class.
void Car::PrintCarData()
{
cout << "The distance that the " << color << " car " << number << " has traveled is: " << distance << "\n";
}
void Car::IncrementDistance()
{
distance++;
}
car_main.cpp
#include <iostream>
#include <string>
#include "car.h"
using std::string;
using std::cout;
int main()
{
// Create class instances for each car.
Car car_1 = Car("green", 1);
Car car_2 = Car("red", 2);
Car car_3 = Car("blue", 3);
// Increment car_1's position by 1.
car_1.IncrementDistance();
// Print out the position and color of each car.
car_1.PrintCarData();
car_2.PrintCarData();
car_3.PrintCarData();
}
6.繼續(xù)擴(kuò)大規(guī)模
1.在下面的代碼中,cp是指向Car對(duì)象的指針,下面兩個(gè)是等價(jià)的:
cp->IncrementDistance();
// Dereference the pointer using *, then
// access IncrementDistance() with traditional
// dot notation.
(*cp).IncrementDistance();
- new在“堆”上為對(duì)象分配內(nèi)存。通常,必須手動(dòng)管理(釋放)此內(nèi)存,以避免程序中出現(xiàn)內(nèi)存泄漏。這很危險(xiǎn),因此通常最好在“stack”上創(chuàng)建對(duì)象,而不使用“new”操作符。
#include <iostream>
#include <string>
#include <vector>
#include "car.h"
using std::string;
using std::cout;
using std::vector;
int main() {
// Create an empty vector of pointers to Cars
// and a null pointer to a car.
vector<Car*> car_vect;
Car* cp = nullptr;
// The vector of colors for the cars:
vector<string> colors {"red", "blue", "green"};
// Create 100 cars with different colors and
// push pointers to each of those cars into the vector.
for (int i = 0; i < 100; i++) {;
cp = new Car(colors[i % 3], i + 1);
car_vect.push_back(cp);
}
// Move each car forward by 1.
for (Car* cp: car_vect) {
cp->IncrementDistance();
}
// Print data about each car.
for (Car* cp: car_vect) {
cp->PrintCarData();
}
}

ok,接下來(lái)將會(huì)更加有趣。