2011-05-09 70 views
5

我有一個簡單的,低級別的容器類,由更高級別的文件類使用。基本上,文件類使用容器在將最終版本保存到實際文件之前在本地存儲修改。因此,一些方法直接從容器類傳遞到文件類。 (例如,Resize()。)從成員複製方法

我剛剛定義了文件類中的方法來調用它們的容器類變體。例如:

void FileClass::Foo() 
{ 
    ContainerMember.Foo(); 
} 

然而,這是一個滋擾。有一個更好的方法嗎?

這裏有一個簡單的例子:

class MyContainer 
{ 
    // ... 

    public: 

    void Foo() 
    { 
     // This function directly handles the object's 
     // member variables. 
    } 
} 

class MyClass 
{ 
    MyContainer Member; 

    public: 

    void Foo() 
    { 
     Member.Foo(); 

     // This seems to be pointless re-implementation, and it's 
     // inconvenient to keep MyContainer's methods and MyClass's 
     // wrappers for those methods synchronized. 
    } 
} 
+0

我在這裏看到構圖,而不是繼承。我錯過了什麼嗎? – 2011-05-09 23:22:57

+0

@Doug我只是問幾個方法,是否有從容器類繼承的方法,或者在我的例子中是'MyContainer'。 (或者更好的解決方案,如果有的話)。我將編輯問題更清楚。 – Maxpm 2011-05-09 23:24:26

+1

在這種情況下,聽起來好像你應該將MyContainer分成一個擁有你想要的方法的類(然後繼承它)和MyContainer的其他方法的其他類。 – dlev 2011-05-09 23:25:44

回答

7

那麼,爲什麼不只是從MyContainer私下繼承,並公開那些你想要轉發的函數呢?using聲明?這就是所謂的「以MyContainer方面實現MyClass

class MyContainer 
{ 
public: 
    void Foo() 
    { 
     // This function directly handles the object's 
     // member variables. 
    } 

    void Bar(){ 
     // ... 
    } 
} 

class MyClass : private MyContainer 
{ 
public: 
    using MyContainer::Foo; 

    // would hide MyContainer::Bar 
    void Bar(){ 
     // ... 
     MyContainer::Bar(); 
     // ... 
    } 
} 

現在的‘外’就可以直接調用Foo,而Bar只是MyClass內到達。如果你現在做一個函數與相同的名稱,它隱藏了基礎功能,你可以用這樣的基礎功能。當然,你現在需要調用完全限定的基礎功能,否則你會進入一個無限遞歸。


另外,我F你要允許MyClass(非polymorphical)子類,比這是罕見的地方之一,被保護的傳承實際上是有用的:

class MyClass : protected MyContainer{ 
    // all stays the same, subclasses are also allowed to call the MyContainer functions 
}; 

非polymorphical如果您MyClass沒有虛析構函數。

1

是,保持一個代理類這樣是很煩人的。您的IDE可能有一些工具使其更容易一些。或者你可以下載一個IDE插件。

但它通常不是非常困難,除非你需要支持幾十個函數和覆蓋和模板。

我平時寫他們喜歡:

void Foo()  { return Member.Foo(); } 
int Bar(int x) { return Member.Bar(x); } 

很高興和對稱。 C++可以讓你在void函數中返回void值,因爲這會使模板更好地工作。但是你可以使用相同的東西來使其他代碼更漂亮。

1

考慮你的情況有什麼意義 - 組合(具有)或繼承(是)MyClass和MyContainer之間的關係。

如果你不想再有這樣的代碼,你幾乎只限於實現繼承(MyContainer作爲基本/抽象基類)。但是,您必須確保這在應用程序中確實是有意義的,並且您不是純粹爲了實現而繼承(實現的繼承很糟糕)。

如果有疑問,你有什麼可能是好的。

編輯:我更習慣於在Java/C#中思考,並忽略了C++具有更大的繼承靈活性Xeo在他的答案中使用的事實。在這種情況下,這只是一個很好的解決方案。

0

這個功能,你需要編寫大量的代碼實際上是必要的功能。 C++是冗長的語言,如果你試圖避免用C++編寫代碼,你的設計永遠不會很好。

但這個問題的真正問題是,這個類沒有任何行爲。這只是一個什麼也不做的包裝。每個班級都需要做一些事情,而不是僅僅傳遞數據。

關鍵是每個班級都有正確的界面。該要求使得有必要編寫轉發功能。每個成員函數的主要目的是將所需的工作分配給全部的數據成員。如果你只有一個數據成員,並且你還沒有決定班級應該做什麼,那麼你擁有的只是轉發功能。一旦添加了更多的成員對象並決定班級應該做什麼,那麼你的轉發功能將會變得更加合理。

有助於這件事的一件事是保持你的課程小。如果接口很小,那麼每個代理類只有很小的接口,接口不會經常更改。

+0

班*做*做些什麼。爲了解決這個問題,我的例子被簡化了。 – Maxpm 2011-05-10 01:51:13