2012-12-06 50 views
0

對不起,我用C++很綠,可能是這種事情嗎?我有一個超類,有一個巨大的構造函數,所以我做了一個靜態工廠類型的構造函數,將做一些工作,然後返回新的ParametricShape(等等等等等等等等等等等等等等等等)。重用子類中的工廠類型構造函數

class ParametricShape: public ModelView{ 

public: 
    //actually has 15 arguments didn't want to type them all up 
    ParametricShape(func x, funcy, funcz, float lu, float hu, float lv, float hv, int sv, int su); 

    static ParametricShape* makeDonutShape(float); 
} 

後來我想在擴展類中使用這個靜態方法。

class Donut : public ParametricShape{ 
    Donut(); 
} 

Donut::Donut(){ 
    this = ParametricShape::makeDonut(1.0f); 
} 

這是諸如此類的事情,我試圖做的,我一直在摸索周圍有各種拷貝構造函數,什麼不可以,並獲得了各種不同的錯誤。目前它只是說:將左值作爲賦值的左操作數。謝謝你的幫助!

+2

*爲什麼*你想要那個?這是沒有意義的...?! –

+0

你不能修改'this'指針。相反,重寫「make ...」方法:它們不應該返回新實例,而是修改現有實例。此外,我認爲你不想重寫你的情況下的形狀類,因爲你不引入任何新的成員,但只提供參數化函數的創建例程 – leemes

+0

@KerrekSB,因爲我想擴展參數化形狀,使其看起來像一個甜甜圈並重寫渲染等一些其他的東西我相當有限,我可以做什麼,因爲我給了一個模型視圖類與prive /受保護的東西,我不允許改變。 – schwiz

回答

0

雖然我與大多數其他的答案一致,你的情況,你不需要經典的工廠模式。正如我所看到的,您希望有一個類來描述具有幾何參數函數的形狀。您希望提供便利的方法來爲某些特殊情況創建這些形狀,例如「甜甜圈」。只要你不想利用任何其他繼承特性,比如重載一些特殊形狀類型的方法,你可以簡單地放下你的其他類,如Donut,並在客戶端代碼中使用「製造商」功能。

使代碼看起來更加面向對象(並保留子類並在客戶端代碼中使用它們的構造函數)的選項,您可以將製造函數重寫爲初始化函數,因爲我想調用它們。請注意,我也介紹了,我們需要在專業類默認的構造函數:

class ParametricShape { 
    func x, y, z; 
    ... 

public: 
    ParametricShape(); 
    ParametricShape(func x, func y, func z, ...); 

protected: 
    void initDonutShape(float); 
}; 


class Donut : public ParametricShape { 

public: 
    Donut(float radius) : 
     ParametricShape()   // call default constructor of ParametricShape 
    { 
     initDonutShape(radius); // initialize functions for "Donut" 
    } 
}; 

現在,實現initDonutShape方法是這樣的:

void ParametricShape::initDonutShape(float radius) { 
    // set the parametric functions 
    x = ... 
    y = ... 
    z = ... 
} 

,而不是返回的ParametricShape一個新的實例。

+0

覆蓋一些渲染的東西正是我想在這裏做的,我希望它總是以某種方式翻譯並具有一定的紋理。不幸的是,這是一個學校項目,我已經提供了一個模型視圖類,我不能改變,他們使這些東西保護/私人。關於init函數的好建議我正要走這條路。乾杯! – schwiz

+0

@schwiz最後,這個方法與你非常相似,但是最重要的改變是:在子類的構造函數中,'ParametricShape'實例已經被創建(這是因爲繼承;你可以避免這種情況)。你只應該修改它,而不是把它扔掉,重新創建另一個。但是,如果您想以不同的方式處理它們(例如,每種類型的一種重載渲染方法),則每個特殊形狀類型只需要一個子類。 – leemes

+0

最後一個注意事項:您也可以在'Donut'構造函數中初始化參數函數。你根本不需要init函數。但是,如果您想要從類型到類型重用它們,例如將紋理與幾何圖形分開並創建木製麪包圈+金屬麪包圈,則它們非常好。但是在這種情況下,給init方法一個有意義的名字,例如「initDonutGeometry」,「initWoodTexture」等等。 – leemes

1

這裏是典型的 「工廠」 模式:

#include <memory> 

struct Shape 
{ 
    enum Type { Donut, Sphere, Teapot }; 

    static std::unqiue_ptr<Shape> make(Type type); 

    virtual ~Shape() = default; 

    // ... 
}; 

struct Donut : Shape 
{ 
    // ... 
}; 

std::unique_ptr<Shape> Shape::make(Shape::Type type) 
{ 
    switch(type) 
    { 
     case Donut: return { new Donut; } 
     default: return { }; 
    } 
} 

用法:

auto p = Shape::make(Shape::Donut); 
0

是的,這是可能的... :)

#include <new> 
Donut::Donut() { 
    this->~Donut(); 
    new (this) (*((Donut*) ParametricShape::makeDonut(1.0f))); 
} 

確保您有定義的複製構造函數, this->~Donut();確保所有分配的vi默認的構造函數被刪除,第二行new (this) ((Donut*) ParametricShape::makeDonut(1.0f));首先創建一個甜甜圈對象,將其重新解釋爲甜甜圈[小心,這裏沒有問題,因爲甜甜圈沒有定義任何變量而不是它的父項]並調用複製構造函數...

新的(這)將不會分配從內存中的任何新的存儲,它只是調用構造:)

+0

雖然很有創意,但這個答案並沒有太大幫助,因爲它會導致非常糟糕的代碼設計。我相信你的回答很諷刺。 – leemes

+0

我很肯定你不能在對象構造之前調用析構函數。另外,我覺得'makeDonut'已經調用了構造函數,這會導致無限遞歸。 –

+0

不,實際上你可以調用析構函數。這是在C++ 11之前重新使用構造函數的一種常用模式。此外,根據所提問題,ParametricShape :: makeDonut不會調用Donut(),這是一個罕見的地方,您不想更改已經設計的地方代碼,但想要添加擴展併爲更乾淨的API創建包裝,但內部髒了。這個代碼很有用! –

相關問題