2010-09-21 70 views
2

我知道這個問題有解決的問題,但我仍然無法弄清楚如何解決我的問題。如何將一個子類分配給基類?

我有這樣的事情:

class Base 
{ 
    static Base* createBase() 
    { 
     Base *b = new Base(); 
     ... //does a lot of weird things 
     return b; 
    } 
} 

class Child : public Base 
{ 
    static Child* createChild() 
    { 
     Child *c = createBase(); // error 
     return c;   
    } 
} 

我知道爲什麼它不工作,但我必須找到一個方法來做到這一點。 createBase函數做了很多事情,所以我不想重新編碼它。

有什麼建議嗎?

+1

好的,爲什麼你必須找到一種方法來做到這一點?認真。你知道你不能那樣做,而你爲什麼不能這麼做。爲什麼你絕對必須有一個不指向'Child'的Child *'? – 2010-09-21 16:19:55

+0

另一個想法:「孩子」必須是「基地」的孩子嗎?它能包含一個'Base'嗎? (很可能不是,但你沒有足夠的話讓我知道。) – 2010-09-21 16:29:37

+0

如果你把「奇怪的東西」移到'Base'構造函數中,那麼'createChild'就可以'返回新的子類'。 – 2010-09-21 17:17:12

回答

1

您應該使用

Child *c = new Child(); 

否則,你要創建一個基類的實例,並稱之爲一個孩子。

RE您的評論:

也許你可以改變

static Base* createBase(); 

static void createBase(Base *b); 

如果您通過實例進入這個方法,你可以用這兩個孩子和基地

例如使用它:

Base *b = new Base(); 
Base::createBase(b); 

Child *c = new Child(); 
Base::createBase(c); 

或者

static Base *createBase(Base *b = NULL){ 
    if(b == NULL){ 
     b = new Base; 
    } 
    //do your stuff 
    return b; 

,併爲孩子:

static Child* createChild(){ 
    Child *c = new Child; 
    createBase(c); 
    return c; 

這種方式,您可以同時使用:

b = Base::createBase(); 
c = Child::createChild(); 
+0

但我想做所有這些奇怪的東西createBase做....沒有複製/粘貼,因爲它是一個非常大的方法。 – sara 2010-09-21 16:11:21

+1

難道這怪異的東西被移動到基礎構造函數而不是靜態方法? – GWW 2010-09-21 16:12:28

+0

對不起,我應該提到我無法修改基類。 – sara 2010-09-21 16:15:55

1

也許你應該重新定義createBase如下:

template< class TheClass > static TheClass* create() 
{ 
    TheClass *ret = new TheClass(); 
    ... //does a lot of weird things 
    return ret; 
} 

你然後可以創建一個對象如下:

Child* pChild = create<Child>(); 

這可能不合適,具體取決於「奇怪」的事情,但它是解決您的問題的一種可能方式。

9

你爲什麼期望這樣工作?您不能將Base對象看作是Child對象,因爲Child類可能具有Base不具有的所有附加數據。

爲了得到你要尋找的效果,有兩種方法可以做到這一點:

第一種方式,也可能是最好的辦法,是把邏輯從createBase移動到Base構造。無論您是創建Base還是從中派生的東西,Base構造函數都會運行。看起來你正在嘗試初始化基礎對象,這正是構造函數的用途!

如果由於某種原因,這不會工作你的情況,另一種選擇是建立在Base保護initialize方法,它接受一個Base*和做所有你正在做的createBase的工作,例如

class Base 
{ 
    public: 

    static Base* createBase() 
    { 
     Base* b = new Base(); 
     initialize(b); 
     return b; 
    } 

    protected: 

    static void initialize(Base* b) 
    { 
     ... //does a lot of weird things 
    } 
} 

class Child : public Base 
{ 
    public: 
    static Child* createChild() 
    { 
     Child *c = new Child(); 
     initialize(c): 
     return c;   
    } 
} 

需要注意的是這個作品,因爲當你不能把一個Base*就好像它是一個Child*,你可以其他方式和治療Child*,就好像它是一個Base*,因爲Child由於繼承的性質,類至少保證了類的所有功能。

編輯:我看見你在評論後到另一個答案,你不能修改Base定義。在這種情況下,你完全沒有運氣,並且考慮到限制條件,你將不得不接受複製和粘貼的需要。如果您無法修改其代碼,您將無法致電createBase並取回指向除Base以外任何類型對象的指針。

+0

我認爲你最好是初始化一個虛擬成員函數而不是靜態的,因爲這樣可以讓你在子類中添加任何「進一步」初始化,同時仍然從派生類函數調用基類函數......但除此之外,好的答案:) – Goz 2010-09-21 16:20:41

+0

@Goz True,但出於同樣的原因,代碼應該在構造函數中放在第一位。 – 2010-09-21 16:22:03

+0

他所需要的只是把東西放在構造函數中。沒有其他要求。 – 2010-09-21 17:00:16

1

不要讓「奇怪」的東西屬於Base構造函數。那麼通過構建孩子你的基地得到適當的構建?

否則只是將代碼重構爲您從兩個地方調用的方法 - 一定不要複製它。

0

您可以使用構造函數來完成這些工作你:

class Base 
{ 
    Base() 
    { 
    // does a lot of weird things 
    } 

    static Base* createBase() 
    { 
    return new Base(); 
    } 

}; 

class Child : public Base 
{ 
    Child() 
    { 
     // Do child's weird things here   
    } 

    static Child* createChild() 
    { 
    return new Child(); 
    } 
}; 

Base *instance1 = new Child(); // Works as expected 
Base *instance2 = Child::createChild(); // Works as expected 
Base *instance3 = new Base(); // Works as expected 
Base *instance4 = Base::createBase(); // Works as expected 

編輯:
如果您不能修改基類,你不應該從中獲得這種方式。該類顯然意味着有自己的功能,而靜態構建方法則提出了一些更復雜的用法。您可能需要使用Decorator設計模式,而不是繼承在這種情況下:http://en.wikipedia.org/wiki/Decorator_pattern

0

這個怎麼樣

class Base 
{ 
public: 
    static Base* createBase() 
    { 
     Base *b = new Base(); 
     //does a lot of weird things 
     return b; 
    } 
}; 

class Child 
{ 
    protected: 
    Base* m_basePtr; 

public: 
    operator Base&(){return *m_basePtr;} 
    static Child* createChild() 
    { 
     Child *c=new Child; 
     c->m_basePtr=Base::createBase(); 
     return c;   
    } 
}; 

,但你必須在析構函數

0

你想要做什麼要刪除的指針是:

class Base 
{ 
    Base() 
    { 
     ... //does a lot of weird things 
    } 
}; 

class Child : public Base 
{ 
    Child Child() // This calls the base constructor auto-magically 
    { 
    } 
} 

int main() 
{ 
    Child childOne; 
    Base baseOne; 

    Child* childPtr = new Child(); 
    Base* basePtr1 = new Child(); 
    Base* basePtr2 = new Base(); 
} 
2

重載新的基類可能會解決您的問題。

類UTIL {

static size_t size; 

公共: 靜態無效的setSize(爲size_t噸) { //互斥保護 大小= T; }

static size_t getsize(); // should only be called from inside new of class A 

};

class A { int i;

市民: 靜態A * createA(){

A* a = new A(); 
    a->i = 10; 
    return a; 
} 

void *的new操作符(爲size_t大小)擲(爲const char *){

無效* P =的malloc(UTIL ::的getSize());

if(p == 0)throw「allocation failure」;

return p;

}

void運算符刪除(無效* P){

免費(P); }

};

size_t UTIL :: size = sizeof(A);

爲size_t UTIL ::的getSize() {

//mutex protection 
    size_t tmp = size; 
    size = sizeof(A); 
    return tmp; 

}

B類 {

公共: 詮釋J; 靜態B * createB() {

  //take mutex 

    UTIL::setSize(sizeof(B)); 
    B* b = (B*)(A::createA()); 
    b->j = 20; 
    //release Mutex 
    return b; 
} 

};

相關問題