2014-02-16 29 views
0

我有一些代碼有點像這樣:如何在命名聯合中使用構造函數?我怎樣才能在以後更改同一個聯合實例中的值? C++/C++ 11

class Token{ 
    public: 

    union tester{ 
     double literal; 
     string name; 

     tester(double op) : literal(op) {}; 
     tester(string val) : name(val) {}; 
     tester(): tester(0.0) {}; 
    }; 

    void setUp(){ 
     //the literal and name members of tester should be initialized here 
    }; 
    /*other functions are below, two of which require that the values of literal 
     and name can be changed*/ 
}; 

我需要來初始化文字和名成員,但我不知道怎麼樣。我已經試過做一個類型測試器的變量,並做到這一點:測試器測試(45.0);但是,我只能設置其中一個成員變量,並簡單地使用測試儀(45.0);不工作,或者我試過這個:令牌的東西; thing.name =「Elly」,那沒用。我的類也不使用構造函數。所以,我的問題是,我如何設置,然後在Token中的測試器中更改成員變量的值?

我正在使用C++ 11編譯器。如果這個問題已經回答了,或者太愚蠢了,我一直在環顧四周,但我真的不明白我如何才能使這個工作。我錯過了一些東西,但我我不太清楚是什麼。)

+3

你知道'union'的成員共享相同的內存嗎?有沒有可能你真的想要一個'struct'? – Nabla

回答

1

簡而言之:不要這樣做

工會代表,具有相同的二進制表示的數據,例如,當真正最好的使用:

union v4f { 
    float f[4]; 
    struct { 
     float x; 
     float y; 
     float z; 
     float t; 
    }; 
}; 

v4f v; 
v.f[1] = 2.f; 
v.t = 0.f; 

假設你真的想在這裏使用一個聯盟,而不是一個結構,即一個令牌包含一個名字或者是一個文字,但不能同時存在,而且您確實需要保存額外的存儲空間,以便使用結構將花費的成本:
在C++ 11之前,您無法使用非=平凡的聯合成員析構函數,比如你的tester.name字符串字段。有關更多詳細信息,請參閱this question

現在,這是可能的,但我會建議不要這樣做,除非你真的知道發生了什麼。要做到這一點,你需要定義你的聯合體的析構函數,因爲編譯器無法決定刪除哪個非重要的聯合成員。我想你是關閉避免這更好的,因爲這不是一個容易回答的問題,沒有任何附加信息:

~tester() { 
// delete name member or not ? 
// very hard to decide without additional data 
} 

至於如何訪問你的工會成員,因爲你的工會是不是匿名的,它可以」 t是匿名訪問的,所以你需要用這個聯合類型實際創建一個類的成員,並引用該類成員。

class Token { 
public: 
    union tester { 
     double literal; 
     string name; 

     tester(double op) : literal(op) {}; 
     tester(string val) : name(val) {}; 
     tester(): tester(0.0) {}; 
     ~tester() {} 
    }; 
    tester data; 
    ... 
}; 

... 
Token t; 
t.data.name = "Elly"; 
+0

好吧,現在更有意義了,謝謝! (以及參考鏈接)。然後如果我在我的類中創建了一個union的成員,比如data,我可以這樣做:'data.name =「Elly」;'然後在另一個地方做這個'data.name =「Fred」;'在我的類中太?如果類型更相似,比如我使用'enum class'類型,情況會更好。 – user3314717

0

聯合的另一個用例是爲所有必須存儲的可能對象分配「足夠」的內存,但一次只能分配一個。

示例: 擁有一個狀態機,它將每個狀態表示爲一個類的實例。狀態機自身包含一個由所有類組成的聯合體。輸入一個狀態將很簡單,可以通過在聯合地址處的運算符new來完成,而通過手動調用析構函數來完成狀態。

還有一個經常出現的用例:通過工會鑄造。我認爲這是一個非常可怕的反模式:-)

回到問題: 初始化兩個成員在同一個!工會內部永遠不可能有時間。第二個init將覆蓋第一個初始化對象的數據。也許你想要一個結構,或者你必須再次考慮你的設計。

+0

哦!那好吧,這是有道理的。然後,如果另一個成員是一個枚舉類類型,比如'enum class Oper {OPP,ERR};',所以'Oper name;'而不是一個字符串和'srting名稱'',那麼,只要我不試圖讓兩個成員立即初始化,我可以設置一個名稱,從enum類的一些線索,然後來改變的東西,並設置文字的值,而不是? – user3314717

+0

原則上,您一次只能在一個工會中存儲一件物品。有關方面,請避免使用C++代碼中的工會。對於工會來說,現實世界中的使用案例很少。工會傾向於將代碼從功能中分離出來,這打破了面向對象編程的基本思想。這聽起來是你在思考過程中的想法。我會建議你開始閱讀一本面向對象設計的好書。也許你應該用你的設計問題開始一個新的問題,並且不要求一個糟糕的解決方案的問題;) – Klaus

+0

好的,這很好理解,雖然在這種情況下,聯盟是我們完成的骨架類的一部分對於一項任務,所以我可能會因爲拿出來而放棄標記。雖然沒有它可能更容易做到。這並不是來自賦值的確切代碼,賦值不會在聯合中使用字符串。但是,是的,我給出的代碼不是很好,現在我可以回顧並欣賞它。^_ ^;謝謝你的幫助 :) – user3314717

相關問題