2012-01-14 62 views
0

我不是一個非常有經驗的c + +編碼器,這讓我難住。我將一個對象(創建在其他地方)傳遞給一個函數,我希望能夠將該對象存儲在某個數組中,然後運行該數組來調用該對象的函數。下面是一些僞代碼:試圖將一個對象存儲在一個數組中,但如何調用該對象的方法?

void AddObject(T& object) { 
    object.action(); // this works 

    T* objectList = NULL; 
    // T gets allocated (not shown here) ... 
    T[0] = object; 
    T[0].action(); // this doesn't work 
} 

我知道對象傳遞正確的,因爲object.action()第一個呼叫做什麼它應該。但是當我將對象存儲在數組中時,嘗試調用action()會導致嚴重的崩潰。

可能我的問題是,我只是簡單地用。和*來修飾,直到它編譯,T[0].action() compliles但在運行時崩潰。

+0

您正在創建*指針數組*和努力在裏面存儲* objects *。這絕對不行,它通常不應該編譯。還有其他錯誤。我真的看不到這是如何編譯的。 – Jon 2012-01-14 02:05:44

+0

這是你的真實代碼嗎?因爲那真的不應該編譯('T [0]'如果'T'是一個類型是沒有意義的。如果使用'objectList',那麼它仍然不能編譯,因爲'objectList [0]'是鍵入'T *',而'object'類型爲'T&') – Grizzly 2012-01-14 02:08:13

+0

T是一個類。這只是僞代碼,我試圖從幾個分散的地方提取樣本。 – 2012-01-14 02:09:36

回答

1

對於你的問題最簡單的答案是,你必須正確聲明你的容器你必須爲你的類定義一個合適的assigment操作符。從你的例子儘可能密切合作:

typedef class MyActionableClass T; 
T* getGlobalPointer(); 

void AddInstance(T const& objInstance) 
{ 
    T* arrayFromElsewhere = getGlobalPointer(); 

//ok, now at this point we have a reference to an object instance 
//and a pointer which we assume is at the base of an array of T **objects** 
//whose first element we don't mind losing 

//**copy** the instance we've received 
    arrayFromElsewhere[0] = objInstance; 

//now invoke the action() method on our **copy** 
    arrayFromElsewhere[0].action(); 

}

注簽名更改爲const引用其中強調,我們要複製原始對象,不以任何方式改變它。

而且筆記仔細是arrayFromElsewhere [0] .action()不是一樣objInstance.action(),因爲你已經做了一個副本 - 行動()被在不同的上下文中調用,不管有多相似。

雖然很明顯你已經濃縮了,但是這樣做的原因並不那麼明顯 - 例如指定你想要維護一個回調對象數組會更好地滿足「需要」這個能力。像你這樣使用「T」也是一個糟糕的選擇,因爲這往往意味着大多數有經驗的C++程序員都會使用模板。

最有可能導致您的「不明原因」崩潰的事情是賦值運算符;如果你沒有定義一個,編譯器會自動生成一個作爲按位副本的工具 - 幾乎可以肯定地是而不是如果你的類不是簡單數據類型(POD)的集合,你想要什麼。

爲了在任何複雜類別上正常工作,您可能需要定義深層副本或使用引用計數;在C++中,讓編譯器爲您創建任何ctor,dtor或賦值幾乎總是一個糟糕的選擇。

而且,當然,使用標準容器而不是您的示例中隱含的簡單數組機制將是個不錯的主意。在這種情況下,由於容器和算法的假設,你應該也可以定義一個默認的ctor,一個虛擬的dtor和一個copy。

如果,事實上,你想創建對象的副本,但希望,相反,在一個陣列中調用對象,但是從動作(),那麼你就需要一個數組的指針來代替。再次緊密合作,以你原來的例子:

typedef class MyActionableClass T; 
T** getGlobalPointer(); 

void AddInstance(T& objInstance) 
{ 
    T** arrayFromElsewhere = getGlobalPointer(); 

//ok, now at this point we have a reference to an object instance 
//and a pointer which we assume is at the base of an array of T **pointers** 
//whose first element we don't mind losing 

//**reference** the instance we've received by saving its address 
    arrayFromElsewhere[0] = &objInstance; 

//now invoke the action() method on **the original instance** 
    arrayFromElsewhere[0]->action(); 

}

注意密切注意arrayFromElsewhere現在的對象指針,而不是實際對象的數組的數組。

注意,我放棄了const修飾在這種情況下,因爲我不知道,如果行動()是一個const方法 - 有了這樣的名字我假設不...

注意仔細號(地址 - 的)運營商正在使用的任務。

還要注意通過使用pointer-to運算符來調用action()方法的新語法。

最後注意,使用指針的標準集裝箱是充滿了內存泄漏的危險,但通常不作爲危險的,因爲使用裸陣列: -/

+0

謝謝你的回答,你似乎明白我正在嘗試做什麼。我認爲你對自動賦值運算符是正確的,正如成功的編譯和可怕的崩潰所證明的那樣。嘗試使用抽象類也有一些麻煩,但我已經完成了排序。 – 2012-01-14 07:22:07

0

我很驚訝它編譯。你聲明一個數組,指向T的8個指針。然後你分配T[0] = object;。這不是你想要的,你想要的是

T objectList[8]; 
objectList[0] = object; 
objectList[0].action(); 

T *objectList[8]; 
objectList[0] = &object; 
objectList[0]->action(); 

現在我在等待一個C++高手一個解釋,爲什麼你的代碼編譯,我真的很好奇。

+0

編輯該問題以修復我聲明objectList = NULL的方式。這不是真正的代碼,只是一個快速示例。 – 2012-01-14 02:15:05

+0

不改變任何相關。你聲明的指針(用作數組)是'objectList',所以在分配之後,'objectList =(T *)malloc(8 * sizeof(T));','objectList = new T [8];' ,你設置'objectList [0] = object;'。 – 2012-01-14 02:30:42

0

你可以把對象要麼變成動態或靜態數組:

#include <vector> // dynamic 
#include <array> // static 

void AddObject(T const & t) 
{ 
    std::array<T, 12> arr; 
    std::vector<T>  v; 

    arr[0] = t; 
    v.push_back(t); 

    arr[0].action(); 
     v[0].action(); 
} 

這並不真正使一個很大的意義,但是,你通常會在函數之外的其他地方定義你的數組。

相關問題