對象數(shù)組

在之前的博客中,我們舉了各種實(shí)例化對象的例子。但是,大家有沒有思考過一個(gè)問題:如果我要實(shí)例化的對象是一個(gè)“群體”,比如,一個(gè)班的同學(xué),或者一個(gè)球隊(duì)的運(yùn)動(dòng)員,那應(yīng)該怎么進(jìn)行實(shí)例化呢?難道一個(gè)班有50個(gè)人,就要分別實(shí)例化50個(gè)對象嗎?這顯然是不現(xiàn)實(shí)的。在C++中,我們可以把他們實(shí)例化為一個(gè)對象數(shù)組,也就是“一組”對象。

今天就給大家分別介紹從棧中實(shí)例化對象數(shù)組和從堆中實(shí)例化對象數(shù)組,以及訪問對象數(shù)組中每個(gè)元素的成員的方法。

首先,我們定義一個(gè)Teacher類,類中包括public修飾的構(gòu)造函數(shù)、析構(gòu)函數(shù)以及數(shù)據(jù)封裝函數(shù),private修飾的數(shù)據(jù)成員。然后我們來看一下怎么實(shí)例化對象數(shù)組。

#pragma once
#include <string>
using namespace std;

class Teacher
{
public:
    Teacher();
    ~Teacher();
    void setName(string _name);
    string getName();
    void setAge(int _age);
    int getAge();
private:
    string m_strName;
    int m_iAge;
};

我們在頭文件Teacher.h中定義了Teacher類,為了減少篇幅,我這里就不展示函數(shù)定義的代碼了。在demo.cpp中。

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

int main(void)
{
    Teacher t[4];
    t[0].setName("Jack");
    t[0].setAge(25);
    t[1].setName("Mary");
    t[1].setAge(21);
    for (int i = 0; i < 4; i++)
    {
        cout << t[i].getName() << " " << t[i].getAge() << endl;
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}

我們實(shí)例化了一個(gè)含有4個(gè)元素的對象數(shù)組。在這里,我們只對前兩個(gè)對象元素進(jìn)行賦值操作,然后用for循環(huán)打印出所有對象元素中的數(shù)據(jù)成員。


image.png

可以看到,對象數(shù)組中的4個(gè)元素的數(shù)據(jù)成員都被打印了出來,由于沒有對t[2]和t[3]進(jìn)行賦值操作,它們被賦予了系統(tǒng)默認(rèn)值(字符串為空,整數(shù)為-858993460)。從構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用情況來看,實(shí)例化了幾個(gè)元素的對象數(shù)組,就會(huì)調(diào)用幾次構(gòu)造函數(shù);運(yùn)行結(jié)束時(shí),也就會(huì)調(diào)用幾次析構(gòu)函數(shù)。

從堆中實(shí)例化數(shù)組對象,會(huì)比較復(fù)雜一些。接下來讓我們看一下從堆中實(shí)例化對象數(shù)組的例子。我們將main函數(shù)改寫成這樣。

int main(void)
{
    Teacher* p = new Teacher[3];
    p->setName("Jack"); //第一個(gè)
    p[0].setAge(25);
    p++;
    p->setName("Mary"); //第二個(gè)
    p[0].setAge(21);
    p[1].setName("Paul"); //第三個(gè)
    p++;
    p->setAge(30);
    for (int i = 0; i < 3; i++)
    {
        cout << p->getName() << " " << p->getAge() << endl;
        p--;
    }
    p++;
    delete[]p;
    p = NULL;
    system("PAUSE");
    return EXIT_SUCCESS;
}

我們從堆中實(shí)例化了一個(gè)對象指針p,讓它指向了一個(gè)對象數(shù)組而非一個(gè)單一的對象。那么如何對對象元素進(jìn)行訪問呢?原理是利用指針p的移動(dòng)。在C語言中,我們知道指針指向數(shù)組的地址就是數(shù)組中第一個(gè)元素的地址,在C++中也是如此。如果直接用p指向的對象元素的setName函數(shù),就是指向第一個(gè)元素的setName函數(shù);同樣,我們不用指針符號,也可以用p[0].setName,效果是完全一樣的。如果要訪問第二個(gè)元素,可以讓指針p向后移一位,也就是p++,然后再指向元素中的函數(shù);也可以直接用p[1].函數(shù)名這樣的形式。但是值得一提的是,如果指針向后移動(dòng)了一位,那么這時(shí)候p->函數(shù)名指向的不再是第一個(gè)對象元素的函數(shù),而是第二個(gè),同理p[0]也指向的是第二個(gè)元素,p[1]也就指向了第三個(gè)元素。如上面的代碼所示,這樣就可以完成全部三個(gè)對象元素的賦值。

那么,如何將這三個(gè)對象元素的數(shù)據(jù)成員打印出來呢?這也是一個(gè)問題,因?yàn)樵谖疑厦尜x值部分的代碼結(jié)束之后,p是指向該對象數(shù)組的最后一個(gè)元素的,我們不能通過for循環(huán)直接用p[i]的形式來打印。于是,我們可以直接倒序打印。先打印最后一個(gè)對象元素中的數(shù)據(jù)成員,然后指針向前移動(dòng)一位,使它指向倒數(shù)第二個(gè)對象元素,再進(jìn)行打印......如此循環(huán)三次,就可以打印出所有對象元素的數(shù)據(jù)成員。

注意到代碼中,for循環(huán)結(jié)束后,還多寫了一句"p++;",可能有人不知道這一步是干什么用的,覺得多此一舉。其實(shí)不然,我們可以仔細(xì)想一下,循環(huán)結(jié)束時(shí),p指向了哪里?它是指向第一個(gè)元素的嗎?答案是否定的,由于在之前我們只對p進(jìn)行了兩次p++,而在for循環(huán)中我們進(jìn)行了三次p--,于是p這時(shí)候就指向了一個(gè)非法的位置。很顯然,我們不能去釋放一段根本就沒有分配給我們的內(nèi)存。所以,需要再進(jìn)行"p++",使p重新指回對象數(shù)組的首元素,然后才能進(jìn)行釋放空間的操作。在釋放時(shí),要注意p指向的是數(shù)組,delete后要加上中括號。

最后看一下運(yùn)行的結(jié)果。


運(yùn)行結(jié)果2

可以看到調(diào)用了三次構(gòu)造函數(shù)和三次析構(gòu)函數(shù),并且析構(gòu)函數(shù)在程序運(yùn)行結(jié)束之前被調(diào)用。

以上就是有關(guān)對象數(shù)組的內(nèi)容,下一篇:對象成員。

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

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

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