2014-02-16 167 views
0

假設我有一個類結構等(簡化了實際的類我有)的不同排列:創建類來表示一個類型

class Graph 
{ 
}; 

class DerivedGraph : public Graph 
{ 
}; 

class DerivedGraph2 : public Graph 
{ 
}; 

我想擴大這種結構,以考慮在同一圖形的不同變化。理想情況下,我想能夠做這樣的事情:

class Graph 
{ 
}; 

// Removed 
//class DerivedGraph : public Graph 
//{ 
//}; 

// Removed 
//class DerivedGraph2 : public Graph 
//{ 
//}; 

class DerivedGraph3 : public Graph // really just a mode of DerivedGraph 
{ 
}; 

class DerivedGraph4 : public Graph // really just a second mode of DerivedGraph 
{ 
}; 


class DerivedGraph5 : public Graph // really just a mode of DerivedGraph2 
{ 
}; 

class DerivedGraph6 : public Graph // really just a second mode of DerivedGraph2 
{ 
}; 

但是你可以很快看到這裏的問題 - 我有在這裏創建了太多的類。此外,基類非常複雜和龐大(底線是它只是簡單的吸引)...所以我不想做太多的結構改變。我希望能夠靈活地在圖形本身的層面上定義事物,但同時還可以靈活地爲一種圖形類型的特定模式定義事物。我希望能夠使用諸如DoesGraphSupportNormalizedData()之類的虛函數或類似的東西(這只是一個簡單的例子)。然後每個類將覆蓋此方法。

另一個想法我是創建模式自己單獨的類結構(Graph類將創建它的一個實例),如:

class BaseMode 
{ 
}; 

class Mode1 : public BaseMode 
{ 
}; 

class Mode2 : public BaseMode 
{ 
}; 

現在的問題是,這些模式類需要訪問從Graph類的幾條數據......我真的不想傳遞所有這些信息。模式類將變得毫無用處,並且根本不會靈活。我只是想不出一個乾淨的方式來處理這個問題。我能想到的最好的方式就是讓模式類別盡其所能,而不必將各種垃圾傳遞給它,但現在界面只是愚蠢而尷尬。有任何想法嗎?

+0

我很困惑。你所描述的只是尖叫「使用繼承」。恐怕不知道更多關於模式的實際執行情況,這很難提供幫助。 – pmr

回答

0

您可以使用用戶界面,也可以使用從我的描述中可以收集到的繼承類。

如果你使用一個基類繼承和關閉它只是你不想派生類有隻給他們換了別人(根據情況的private訪問修飾符,然後protectedpublic的事情課程)。這樣你的派生類只需要他們需要的信息。您也可以在每個較低類中設置一個實例變量,以定義每個派生類的相關內容。訪問修飾符是你的朋友。

如果您使用接口只包含每個圖形都需要的所有內容,然後在構建各個類時只需從中自定義它們以包含特色。個人而言,我會通過界面繼承,但這只是我自己。

0

我在這樣的一個問題之前跑了(和現在仍然然後......)

在這種情況下,你可能會採取了錯誤的方式,你看成什麼樣是設備專門功能取決於圖形和模式的類型。繼承是很好的,但它有你提到的限制。尤其是因爲用戶可能想要切換圖形的類型,而保留現有的圖形對象。繼承在這種情況下沒有幫助。

這樣做的一種方法是創建函數,根據當前的類型和模式進行調用。假設你必須畫線,模式可以設置爲LINE或DOTS。可能您畫一條線,是特定的模式或其他兩個功能:

void Graph::draw_line_line(line l) 
{ 
    // draw a line 
} 

void Graph::draw_line_dots(line l) 
{ 
    // draw a dots along the line 
} 

現在你可以定義它代表了它這種類型的渲染功能和可變成員的類型:

typedef void (Graph::*draw_line_func)(line l); 

draw_line_func m_draw_line; 
現在,當你想渲染線

void Graph::set_mode(mode_t mode) 
{ 
    m_mode = mode; // save for get_mode() to work 
    switch(mode) 
    { 
    case LINE: 
     m_draw_line = &Draw::draw_line_line; 
     break; 

    case DOTS: 
     m_draw_line = &Draw::draw_line_dots; 
     break; 

    ... 
    } 
} 

,你調用這個專門功能,您:

隨着在手,你可以喜歡這個節目你SET_MODE()函數,東西不需要知道它是否是一個線或DOTS ......

void Graph::draw_line(line l) 
{ 
    this->*m_draw_line(l); 
} 

這樣,您創建一個間接做出了很多吸塵器具有較大的開關或很多,如果現有的大型功能()語句沒有打破現有的「強大」班,可能變得很難使用(因爲如果它那麼大,它可能已經在使用......)