2015-10-04 103 views
1

基本上,我有兩個類,Peg和Disk。 (這是一個河內計劃的塔)我有的文件是Disk.h,Disk.cpp,Peg.h,Peg.cpp和main.cpp。不知道這是否重要。這裏是Disk.h的磁盤類主類中調用的類方法,更改不會在類方法外持久?

#include <vector> 
#include "gwindow.h" 
#ifndef DISK_H 
#define DISK_H 

class Disk 
{ 
private: 
    int xCoord; //x and y coords are for drawing in a gwindow 
    int yCoord; 
    int mHeight; 
    int mWidth; 
    COLOR mColor; 
    int mName; //helps me keep track of which is which 

public: 
    Disk(); //default constructor 
    Disk(int x, int y, int heightIn, int widthIn, COLOR colorIn); 
    void setXY(int x, int y); //this is the one I'm having trouble with 
    int getHeight(); 
    int getWidth(); 
    int getX(); 
    int getY(); 
    COLOR getColor(); 
    std::string diskColor(); 
    void draw(GWindow &gw); 
    void nameDisk(int name); //yet this one is working? 
    int getName(); 
}; 

#endif 

但是,我遇到了setXY函數的問題。當我從main調用它時,它會正確調用該函數,更改setXY範圍內的變量,但該值不會保留在函數外部。然而,nameDisk工作正常,基本上是一樣的,除了它正在改變mName而不是xCoord和yCoord。這裏是setXY:

void Disk::setXY(int x, int y) 
{ 
    xCoord = x; 
    yCoord= y; 
} 

,這裏是我如何把它從主:

pegVec[2].getDisks()[0].setXY(690, 200); 

我知道這看起來瘋狂,但基本上pegVec是3個掛鉤對象的載體。每個掛鉤對象都有一個函數getDisks(),該函數返回當前掛鉤上所有磁盤的矢量。因此,上面的行試圖在第2個掛鉤上執行setXY。對不起,如果這不清楚,但我已經嘗試製作一個新的磁盤對象並在其上調用它,那也不起作用。

這裏是getDisks,如果它的問題:

std::vector<Disk> Peg::getDisks() 
{ 
    return disksOn; 
} 

和disksOn只是釘的成員變量:

std::vector<Disk> disksOn; 

我認爲這可能是與如何getDisks問題()的作品。我是一個noob,但我猜測,返回矢量disksOn使它的「副本」,這是我改變了我的setXY功能,但它不是相同的實際disksOn矢量相關Peg對象?我不知道這是否合理。

我試過到目前爲止:

  • 製作XCOORD和YCOORD公共變量和更新它們手動,而不是使一個setter函數。這沒有奏效。
  • 我在每一步打印出x和y值。在setXY中,值已成功更新,但是當函數結束時,他們又回到了原來的樣子。
  • 我嘗試了一些與const關鍵字混亂,但我不明白它,甚至無法讓它運行。
  • 通過引用/值傳遞所有內容
  • 在接受Disk矢量作爲輸入並使用getDisks作爲該函數的輸入的main中創建一個新函數。沒有工作,同樣的問題。
  • 測試了我的另一個setter函數nameDisk,它工作正常。它基本上與setXY相同,這就是爲什麼我認爲問題出在getDisks上。
  • 始終在各個點(heh)使用指針,但我不確定這是否是最佳方式。我昨晚搞砸了,所以我不記得100%,但我想我試圖讓getDisks返回一個指針,而不是矢量,我認爲它沒有問題,但它更可能是我的語法問題和我如何使用指針。我認爲這可能有效,但我不知道如何動搖它。

幫助?

回答

0

你是在正確的軌道上 - 不知何故,你正在看的不同於你自己認爲的物體。使用引用是一個很好的解決方案,但你可能沒有得到正確的;-)

嘗試:

// Return reference to the disks on the peg. 
std::vector<Disk>& Peg::getDisks() 
{ 
    return disksOn; 
} 
+0

嗯,工作!非常感謝。我記得昨天晚上試了一下,但是我讓事情變得更加複雜。 –

0

的問題是, std::vector<Disk> getDisks() { return disksOn; } 返回一個完全新的獨立臨時副本 disksOn而不是對原始的引用。所以你正在修改一個在聲明結尾被丟棄的臨時副本。

你需要爲了返回參考到disksOn使用 std::vector<Disk> &getDisks() { return disksOn; }

雖然如果您要返回對矢量成員對象的引用,那麼您可能會將對象直接作爲公共對象訪問,因爲任何人都可以在此處操作矢量,並在服務時擺脫getDisks()函數在訪問保護方面沒有任何目的。

更好的設計是給訪問單個磁盤:

Disk &getDisk(int index) { 
    return disksOn[index]; 
} 

const Disk &getDisk(int index) const { 
    return disksOn[index]; 
} 

背後不給人以矢量直接訪問我們的想法是,如果需要在不改變外部的代碼,你可以稍後更改基礎容器類型Peg類。

第二個版本(const)對於訪問const Peg對象的const Disks是必需的。

+0

感謝您的回答。你能解釋一下const Disk對象和普通Disk對象之間的區別嗎? const Disk對象是不可變的嗎? –

+0

簡單地說:是的。 A ** const **對象是一個不能直接更改的對象,只能調用它的const成員函數。然而,它可以通過對同一對象使用不同的非const指針或非const引用來改變,並且某些函數可能會通過執行必要的const_cast <>()來改變它,例如,用於實現**引用計數對象**作爲引用計數需要更新,即使該對象在概念上被認爲是常量。所以要迂腐,它不是一成不變的。 –

+0

例如'int a = 5; const int&const_ref_a = a; cout << const_ref_a <<「\ n」; a = 10; cout << const_ref_a <<「\ n」; '即使const_ref_a是對a的常量引用,對象'a'也可以被改變。但'const_ref_a = 20;'會產生編譯器錯誤。你必須看到一個** const **引用或指針作爲一種說法,「我不打算用這個引用(或指針)來改變它的值,編譯器請告訴我,如果我不小心做了」而不是「這個值永遠不會改變「,因爲在非常複雜的系統中,您可能會感到驚訝。 –