2011-05-19 20 views
10

說我有兩個的.cpp文件oranges.cppbasket.cpp。他們分別有orangebasket。我的main程序生成許多baskets,而這又產生了許多oranges。所以基本上,main會有很多對象Baskets;和baskets將有許多對象Oranges。如果我在orange中需要知道籃子顏色的功能,我該如何去尋找籃子的顏色?一個棘手的問題OOP我從來沒有得到我的頭周圍

orangle.cpp

class oranges 
{ 
    void whichColorBasket() 
    { 
     // get the color of the basket the orange is in...? 
    } 
} 

basket.cpp

class basket 
{ 
    int color; 

    void basket() 
    { 
     for(int i = 0; i < 10; i++)    
      oranges *o = new oranges; 
    } 
} 

我知道我的語法可能不是完美的,但我怎麼會從一個函數訪問的basket的數據成員在orangeorange是由basket創建的對象)。

發送顏色參數不是一個選項,因爲太多的orange s和basket的顏色可能會在運行時更改。

我在某處讀到靜態函數可以做到這一點,但它們只有在它們位於相同的.cpp文件中時才起作用。

那麼,我該怎麼辦?

+2

我在這裏看到耦合。這是你的問題。您可能想要將指向顏色的指針傳遞給您的橙色,但會破壞封裝。 – 2011-05-19 14:23:56

回答

17

靜態函數幾乎肯定是不這裏的答案。

您可能需要將對「父」Basket的引用傳遞給Oranges對象,然後可以通過詢問來查找顏色。

例如:

class Basket 
{ 
public: 
    void Basket() { 
     Oranges *o = new Oranges(*this); 
    } 

    color getColor() const { ... } 
}; 


class Oranges 
{ 
private: 
    const Basket &myBasket; 

public: 
    Oranges(const Basket &b) : myBasket(b) {} // Store reference 

    color getColor() const { return myBasket.getColor(); } // Interrogate my basket 

}; 

無論您使用指針或引用,將取決於是否能OrangesBasket S之間不斷移動。

3

您需要以某種方式將桔子綁定到它們所屬的籃子上 - 例如,將指針傳遞給籃子。你怎麼做取決於橙子是否可以改變他們在一生中的束縛,以及是否可以在橙子被破壞之前銷燬橙子。

假設橘子從來沒有活得比籃下和永遠不變的籃子,你做這種方式:

class oranges{ 
public: 
    oranges(backet* object) { belongsTo = object; } 
    void whichColorBasket() { 
     here get belongsTo->color; 
    }   
private: 
    backet* belongsTo; 
}; 

class basket{ 
    int color; 
    void basket(){ 
     for(int i=0;i<10;i++)    
      oranges *o=new oranges(this); //pass "current object" 
    } 
}; 
+0

我將如何包含這些文件。截至目前,basket.cpp的第一行是'#include「oranges.h」'我猜測用橘子引用的籃子是行不通的,因爲它不會找到籃子。 – 2011-05-19 14:39:31

+1

這是前瞻性聲明的用途。在oranges.h的頂部添加一行:'class basket;'這將允許橙色頭部包含指針和引用'Basket'而不包含'basket.h'。 (basket.h將有一個'#include「orange.h」',如果orange.h包含basket.h,你將得到一個循環引用,正向聲明打破了這個循環。) – RobH 2011-05-23 07:22:09

+0

謝謝。我無法相信我的CS班從未涉及過這樣的東西。 – 2011-05-25 18:40:02

3

你需要到籃下橙色是

class oranges{ 
    basket* b; 
    int whichColorBasket() { 
     return b->color; 
    } 
} 


class basket{ 
    int color; 

    void basket(){ 
     for(int i=0;i<10;i++){   
       oranges *o=new oranges; 
       o->b = &this; 
     } 
    } 
} 

我忽略了內存泄漏橙色指點參考這裏

2

oranges對象應該有一個實例變量basket代表籃它的英寸添加一個方法putInBasket它需要一個籃子,並將變量設置爲它所在的籃子。然後橙色看着whichColorBasket方法中的變量。如果basketNULL它不在籃子裏。

儘管如此,這不是最好的設計,因爲它提供了不一致的可能性。籃子可能會認爲它有橙色,但橘子的指針可能會指向另一個籃子。 orange真的應該知道籃子的顏色嗎?什麼是用例?如果你只是處理籃子,而你有一個橙子,也許籃子應該有一個isOrangeHere方法,它告訴你一個給定的桔子是否在那裏。你把它放在所有的籃子上,然後你拿出一個返回true的顏色。

1

由於您使用的是C++,因此在您的桔子中使用了一個指針。 int *basket_color;然後就分配給它的籃子的地址顏色basket_color = &color

+0

我認爲這是最好的解決方案。大多數其他解決方案都會傳遞指向籃子對象的指針。將指針傳遞給單個顏色整數反而看起來更安全。 – 2011-05-19 17:28:26

+1

將指針傳遞給Basket的數據成員之一是封裝的一個相當典型的失敗。直接地,你已經授予Orange任何時候改變籃子顏色的能力。 Oli的回答(出現在我的下面)是正確的,OO安全的做事方式。 – RobH 2011-05-23 07:18:09

+0

我的觀點是,將對象指針傳遞給另一個對象會授予其他對象很多特權,例如調用函數和使用成員。傳遞一個成員會將訪問權限隔離爲只有該變量。但是我想你從OO的角度來看是正確的,它會破壞封裝。 – 2011-05-25 18:43:19

2

一個屬性添加到包含父籃參考橘子。在將橙子加入籃子的方法中,也將父母設置爲籃子。

class oranges{ 
    basket* basket; 

    void oranged(basket* bask) 
    { 
     basket = bask; 
    } 
    int whichColorBasket() { 
     return basket->color; 
    } 
} 

class basket{ 
    int color; 

    void basket(){ 
     for(int i=0;i<10;i++)    
       oranges *o=new oranges(&this); 
    }   
} 

此語法可能是錯誤的,但這是它通常的做法。

+0

謝謝。我認爲這是一種可能的解決方案,但似乎並不安全。 – 2011-05-19 14:24:40

+0

如果籃子爲空,則不屬於籃子。你的安全意味着什麼? – 2011-05-19 14:35:35

+0

我的意思是它有點休息封裝。無論如何,我將如何包含這些文件。截至目前,basket.cpp的第一行是#include「oranges.h」我猜測用橘子引用的籃子是行不通的,因爲它不會找到籃子。 – 2011-05-19 14:40:59

0

你的oranges類可能有一個basket成員變量引用包含它的籃子。然後,當oranges對象想要知道其包含的籃子的顏色時,它只會調用myBasket.color的值。

構造函數oranges將不得不初始化這個成員變量,所以它需要一個basket參數。

0

編輯:完全重複這個解決方案,因爲我錯過了一個關鍵的約束。

另一種可能的方法是將一個成員變量添加到orange類,像這樣:

class oranges 
{ 
    private: 
    int m_nBasketID; 

    public: 
    oranges(int nID = 0) 
    { 
     m_nBasketID = nID; 
    } 

    void whichColorBasket() 
    { 
     return gBasketList[m_nBasketID].color; 
    } 
} 

並設置值,而在basket類創建oranges,像這樣:

class basket 
{ 
    static unsigned int nBasketID; 
public: 
int color; 
void basket() 
{ 
    //First basket will have ID = 1 because 
    //0 is reserved for unknown/uninitialized state. 
    nBasketID++; 

    for(int i=0;i<10;i++)    
      oranges *o=new oranges(nBasketID); 

    gBasketList.push_back(*this); 
} 

其他修改如下:

unsigned int basket::nBasketID = 0; 
std::vector<basket> gBasketList; 

我在這裏做了一些假設:

  1. 有一個已知的值(例如零)可用於表示未知/未初始化的顏色狀態。該值可以在oranges的構造函數中使用默認值。
  2. oranges創建後不切換籃子。如果用例需要解決的問題,然後可能你可以刪除從原來的basketorange,並添加一個新的目的地basekt或提供一個成員函數來處理這種情況等
+1

這是一個非常糟糕的解決方案,因爲當桔子不在籃子內部並且/或者取決於誰正在工作時,桔子仍然具有顏色,他可以將桔子從一個籃子中取出並放在另一個籃子中,並且忘記更改顏色... – 2011-05-19 15:10:08

+0

我同意,由於錯過了「籃子的顏色可能會在運行期間發生變化」的限制,因此解決方案並不完整。然而,「橙色不在籃子內部時仍然有顏色」的擔憂是無效的,因爲顏色是橙色的一員,並且可隨時更改。要移動橘子,請參閱原始帖子中的假設#2。 – 2011-05-19 16:05:13

+0

你確實建議(i)公開訪問內部數據成員和(ii)全局*對象列表?哇。 – RobH 2011-05-23 07:29:05

1

避免方式該聯結是要詢問每個籃子是否包含特定的橙子。如果有,請檢查它的顏色。

橘子爲什麼要關心籃子的顏色?另一個籃子裏的蘋果呢?他們也有興趣嗎?

2

簡單的答案是,你沒有。如果你需要的話,在你的設計中有一個問題 : 什麼樣的桔子會知道它在哪個籃子裏?如果桔子不在 籃子裏怎麼辦?

如果您需要以某種方式支持此功能,則「正確」解決方案 將沿着觀察者模式行;你的果實將成爲其容器的觀察者;當您將 水果放入一個容器中時,容器將註冊爲 水果,當您取出水果時,容器將取消註冊 。然後,客戶可以向他們的水果詢問他們當前的容器,然後問任何他們想要的東西。

相關問題