2013-01-23 20 views
0

我想找出一種方法來獲取我的基類的副本,並創建一個引用與基類相同的地址空間的我的子類的實例。擴展一個基類,並維護引用

因此,例如,我在基類Foo中有許多成員,並且在子類Bar中有幾個額外的成員。如何從我的Foo創建一個欄,以便更改xBar也更改xFoo

前)

struct Foo{ 
    int x; 
    Foo(){ 
     x = 0; 
    } 
} 

struct Bar : Foo{ 
    int z; 
    //?? what to do here 
} 

int main(){ 
    Foo foo(); 
    Bar bar(foo); //?? 
    bar.x = 7; 
    assert(bar.x == foo.x); 
} 

我知道這是一個奇怪的問題,我還沒有措辭非常好。如果有人知道一個答案,或者如果我很荒謬,並且在stackoverflow上有一個答案,我無法找到這個答案,我會非常感激。感謝您的時間。

+0

z將如何存儲在「Foo」對象中?實際上你沒有辦法將更多的數據存儲在已經分配好的對象中 - 這是一個stackoverflow問題(我不是說在這個網站上有另一篇文章,但你會寫入數據結構之外的數據 - 這是是從來沒有好!) –

+0

這不是我想要的,z是我在我的酒吧,我需要其他計算額外的價值。 x是我需要改變的東西,如果我改變它爲我的酒吧對象。 –

+2

我懷疑你正在做一個「XY-問題」,你想做X,你認爲Y是解決方案,因此要問如何去做Y.如果你多解釋一下你實際想做的事情,我確定我們可以幫助您解決問題。 –

回答

1

取決於你如何想/能接近這個,你有兩個選擇:

1)的間接

struct Bar 
{ 
private: 
    Bar() = delete; //eradicate the default constructor 
public: 
    //Foo member references 
    int &x; 

    //Bar members 
    int z; 

    Bar(Foo& f): x(f.x) { } //of course, you may initialize z as well 
}; 

用法:

Foo foo_obj; 

//new scope begins (can be a function call, for example) 
{ 
    Bar bar_obj(foo_obj); 

    //do stuff with bar_obj 
    //... 
    //work done 

} //scope ends; bar_obj is destroyed 

//magic! foo_obj has been updated with the correct values all this time 

2)多態性

struct Bar: public Foo 
{   
    //Bar members 
    int z; 

    Bar(): Foo() { } 
}; 

用法:

Foo foo_obj; 

//new scope begins (can be a function call, for example) 
{ 
    Bar bar_obj; 
    static_cast<Foo&>(bar_obj) = foo_obj; //we'll use Foo's default (or user-defined) assignment operator 
    //note that you need to cast to reference 

    //do stuff with bar_obj 
    //... 
    //work done 

    foo_obj = bar_obj; //you will need to copy your data back at this point 
    //also note foo_obj has not been updated during this time, which may not be desirable 
} //scope ends 
+0

Polymorphic方法對我更有吸引力,但是,我在靜態轉換中出現錯誤,表明沒有用戶定義的從foo到bar的轉換存在。 –

+0

@banshee_walk_sly固定。演員應該繼承派生物。 –

+0

優秀!這應該做我想要的。非常感謝你。 –

1

您當前的代碼,使您的Foo的新副本,當你初始化酒吧,這意味着它有它自己的一套存儲內它的結構不同的價值觀。爲了讓Foo和Bar共享一個值,您需要將其更改爲指針或引用。你還需要爲Bar指定一個構造函數,它將Foo作爲參數。

這裏有一種方法可以做到這一點,顯然不是理想的,因爲X的價值是作爲一個全球性存儲的,最終你需要某個地方來存儲它,並確切地取決於你的需求。

int x_storage; 

struct Foo{ 
    int& x; 
    Foo(): x(x_storage){ 
     x = 0; 
    } 
}; 

struct Bar : Foo{ 
    int z; 
    Bar(Foo& f) 
    { 
     x = f.x; 
    } 
}; 

int main(){ 
    Foo f = Foo(); 
    Bar b = Bar(f); //?? 
    b.x = 7; 
    assert(b.x == f.x); 
}; 

編輯:看你的意見,也許inheretence是不是你所追求的一切,你可能只是想用一個「有」關係來包裝一個富一個酒吧裏面,像這樣:

struct Foo{ 
    int x; 
    Foo(){ 
     x = 0; 
    } 
}; 

struct Bar{ 
    Foo& myFoo; 
    int z; 
    Bar(Foo& f): myFoo(f){ 
    } 
}; 

int main(){ 
    Foo f = Foo(); 
    Bar b = Bar(f); //?? 
    b.myFoo.x = 7; 
    assert(b.myFoo.x == f.x); 
}; 
+1

雖然完全按照規定解決了問題,但您會如何去做一些Foo和Bar對象? –

+0

將「x_storage」放在Foo對象中將是可行的,儘管最終存在重複存儲,您可以自由忽略它(儘管內存使用可能成爲問題)。您也可以在堆上分配內存並使用引用計數來確保它正確釋放。 – Jason

+0

foo內部或外部沒有區別,靜態變量不是結構的一部分。是的,在堆棧上分配會工作,但真的有點複雜... :))( –

1

右,所以我goiing假設你還必須創建objeccts的能力:

class Foo // Base class. 
{ 
    public: 
    int x; 
}; 


class Bar 
{ 
    public: 
    int z; 
} 

一些功能:

void frobb(Foo *fooPtr) 
{ 
    if(fooPtr->x != 7) 
    { 
     cout << "Bad value of x\n"; 
    } 
    ... 
} 

.... 

// some of your code (in a different file probably. 

Bar b; 
... do stuff with b. 
b.x = 7; 
frobb(&b); 

除非在API中確實有某些東西被破壞,否則你不應該需要從Foo或Bar中的Foo中創建一個Bar。這只是糟糕的設計。

編輯:

在註釋中所描述的情況:

一些代碼創建一個酒吧對象:

Bar b; 

extern void some_generic_api(Foo *fptr); 

... do stuff with b, including setting your own variables. 

b.x = 7; 
some_generic_api(&b); // WOrks like a "Foo" object without problem. 

... some other bit of code ... 

void frobb(Foo *fptr) 
{ 
    // Note: Don't do this unless you are SURE it's a Bar object you actually have! 
    Bar *bptr = reinterpret_cast<Bar*>(fptr); 

    .. do stuff that requires Bar object using bptr; 
    bptr->x = 19; 

    some_generic_api(bptr); // This will work fine. 
} 
+0

我的問題在於當我進入Windows特定的代碼。我基本上需要添加一個PROCESS_INFORMATION對象到我的Foo。我解決這個問題的方法是在窗口部分添加一個Bar子類並添加額外的對象。但是,我確實修改了其他屬性,我需要修改這些修改。您的代碼需要一個Bar並設置一個值,然後將該Bar作爲Foo傳遞。我需要把Foo當成酒吧。 –

+0

啊,所以在我上面的代碼中,你是「frobb」的所有者? –

+0

是的,我收到Foo,但需要與Bar一起工作。 –

1

只是另一種選擇,沒有人還沒有提到,但如果你想只有在內存中爲Foo的所有對象分配一個變量作爲基類,則可以使用靜態成員變量。

struct Foo{ 
    static int x; 
    Foo() { 
     x = 0; 
    } 
}; 

int Foo::x = 0; 

struct Bar : Foo { 
    int z; 
}; 

int main(){ 
    Foo foo(); 
    Bar bar(); 
    bar.x = 7; 
    assert(&bar.x == &foo.x); // now using the same memory address 
} 

而且,作爲一個說明,static關鍵字在C++語言很多含義,所以我會建議找他們了休息,如果你不熟悉(這裏是msdn page on the C++ static keyword一個MSDN頁面作爲首發),我不能說我用很多頻率(特別是函數範圍的靜態變量)來使用靜態關鍵字的所有含義,但是它們是工具箱中的便利工具,但是如果出現正確的情況。

+0

我喜歡這個主意,這可能對某些人有效。但是,我的代碼使用Foo和Bar的多個實例,這意味着靜態會引用所有對象的數據。 –