2013-07-20 48 views
1

我正在學習C++中的類/繼承/指針是如何工作的,並對以下代碼進行編碼。指向無效函數內的類

我有一個類單元聲明爲這樣:

class unit{ 
    public: 
     int locationX,locationY; 

     //genotype (does not change) 
     float agility, build,size,stamina, aggression; 
     //phenotype (changes based on genotype and stimuli) 
     float speed, strength, hunger; 
}; 

當我創建一個新的實例給進入的空隙功能(下面,分別地),所述存儲器還沒有分配。

實例

unit **units = 0; 

void函數原型

void initialize(grid *grids, unit **units /*, plant **plants, predator **predators */); 

存儲器被使用的一些參數的空隙函數內分配:

void initialize(grid *grids, unit **units,plant **plants,predator **predators) 
{ 
    units = new unit*[int(((grids->gridHeight)*(grids->gridWidth)*(grids->gridDivision))/20)]; 

    for(register int i = 0; i<int(((grids->gridHeight)*(grids->gridWidth)*(grids->gridDivision))/20); i++) 
     { 
     units[i] = new unit; 
     units[i]->hunger = 5; 
     units[i]->locationX = (rand()%((grids->gridWidth)-0)); 
     units[i]->locationY = (rand()%((grids->gridHeight)-0)); 
     //etc, etc 
    } 
} 

然而,一旦I E xit void函數,我剛存儲的數據被刪除。指針聲明和傳入函數有什麼問題(如下所示)?

initialize(&environment, units, plants, predators); 

注意:我只有用單位下單元類中聲明變量的問題。 環境變量很好。另外兩個(植物掠食者)類似單位,所以如果這是固定的,我可以修復其他人。

其次注意:主要功能如下(相關部分):

int main() 
{ 
    unit **units = 0; //<--- Important one 
    plant **plants = 0; 
    predator **predators = 0; 
    grid environment(250,250,5); //Constructor for environment (don't mind this) 
    initialize(&environment, units, plants, predators); //<-- Void function 
    running = true; 

    return 0; 
} 

感謝您的幫助/鏈接/解釋,你可以提供。

+0

@Beta:謝謝你的修復。它現在有效! – asuprem

回答

2

您將units傳遞給函數,值爲。這意味着函數中的指針從調用代碼中的一個副本開始。在該函數中,您爲本地units變量(即一些新創建的對象的地址)分配一個新值。然後,當函數終止時,局部變量超出範圍,它指向的對象將丟失。調用代碼中的指針永遠不會被修改,並且對這些內容一無所知。

傳遞它的引用,而不是:

void initialize(grid *grids, unit ** &units) 
+0

除了按預期工作之外,它還會節省一些開銷 – Trojan

1

你傳遞「單位」作爲一種「單位**」,這是在棧上。當您爲變量「units」分配一個新值時,會影響函數的局部變量。如果你想讓調用代碼更新變量「units」,你必須通過指針或引用來傳遞它。來解決這個

最簡單的方式是將函數簽名更改爲:

void initialize(grid *grids, unit **&units, etc..); 

這是通過可變單元作爲基準的指針的指針的單元。

+0

「將可變單元作爲參考傳遞給指向單元指針的指針」:所以我認爲你也意指'單元**和單元',而不是'單元* &units' :-) – Boris

+0

哎呀是的!謝謝(原來是一個文本格式問題) – Brad

0

在方法內部初始化一個指針(或數組)A * a是修改變量a(在這種情況下是一個指針/數組)的特殊情況。在一個方法中修改一個變量可以通過向它傳遞一個指針或者對它的一個引用來完成。所以如果你的變量已經是一個指針,這兩個選項如下所示。

通過指針傳遞到您的指針a

void init(A * *a) 
{ 
    *a = new A(); // or "new A[n]" if "a" is an array 
} 

void main() 
{ 
    A * a; 
    init(&a); 
} 

或傳遞引用指針:

void init(A * &a) 
{ 
    a = new A(); // or "new A[n]" if "a" is an array 
} 

void main() 
{ 
    A * a; 
    init(a); 
} 

所以你的情況,aunit*數組(我認爲順便提一下,最好是簡單地使用一個unit的數組,並且從這個循環中保存,以便分開動態分配所有單元),所以基本上a是01型所以你的A實際上是unit*的類型。使用第二種方法會導致:

void init(unit* * &units) 

但正如我所說,這可能是更好的只是使用的unit數組,而是和你的整個代碼看起來像:

void initialize(unit * &units /* etc */) 
{ 
    // note that I use unit instead of unit* here 
    units = new unit[n]; 

    for(register int i = 0; i<n; i++) 
    { 
     // note that I remove the "new unit;" here 
     // note that I use "." instead of "->" 
     units[i].hunger = 5; 
     units[i].locationX = (rand()%((grids->gridWidth)-0)); 
     units[i].locationY = (rand()%((grids->gridHeight)-0)); 
     //etc, etc 
    } 
} 

void main() 
{ 
    unit * units; 
    initialize(units); 
}