3.Writing Larger Programs

要想寫一個(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)題。

  1. 當(dāng)類方法在類之外定義時(shí),必須使用scope resolution操作符::來(lái)指示該方法屬于哪個(gè)類。例如,在PrintCarData方法的定義中可以看到:
void Car::PrintCarData()

如果有兩個(gè)類的方法具有相同的名稱,這可以防止任何編譯器問(wèn)題。

  1. 改變了構(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)行初始化。

  1. 不需要在類外部可見(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();
  1. 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ì)更加有趣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容