2011-03-11 12 views
20

क्या सी ++ में एक संघ का सदस्य कार्य हो सकता है? यदि कोई ऑब्जेक्ट बनाया गया है तो डेटा सदस्यों और सदस्य फ़ंक्शंस के साथ संघ कैसे मौजूद है?सी ++ में यूनियन वे व्यवहार्य हैं

यदि मुझे हां लगता है, तो क्या वे कहीं भी व्यवहार्य हैं। यदि हां तो कहाँ?

उत्तर

31

9,5/1

एक संघ सदस्य कार्यों (निर्माणकर्ता और विनाशकर्ता सहित) हो सकता है, लेकिन आभासी नहीं (10.3) कार्य करता है। एक संघ के पास कक्षाएं नहीं होंगी। एक संघ का उपयोग आधार वर्ग के रूप में नहीं किया जाएगा। एक गैर तुच्छ निर्माता (12.1), एक गैर तुच्छ प्रतिलिपि निर्माता (12.8), एक गैर तुच्छ नाशक (12.4), या एक गैर तुच्छ प्रति असाइनमेंट ऑपरेटर (13.5 के साथ एक कक्षा की एक वस्तु। 3, 12.8) एक यूनियन का सदस्य नहीं हो सकता, और न ही इस तरह के वस्तुओं

की एक सरणी क्या तुम कैसे डेटा के सदस्यों और सदस्य कार्यों मौजूद साथ संघ कर एक वस्तु बन जाता है, तो मतलब है सकते हैं? सदस्य कार्य (गैर-वर्चुअल) किसी वर्ग/संघ के उदाहरण में कोई स्थान नहीं लेते हैं।

+1

+1, मुझे कभी नहीं पता था कि आप संघों के साथ ऐसा कर सकते हैं। कुछ नया रोज़ाना सीखें ... –

+0

+1 जो कुछ मुझे नहीं पता था और लिखा नहीं था "मेरे लिए काम करता है" – Flexo

0

मुझे नहीं पता कि यह मान्य है या नहीं। Codepad, स्वीकार करता है चलाता है, और

union x { 
    int t; 
    int k() { return 42;}; 
}; 

int main() { 
    x y; 
    y.t = y.k(); 
    std::cout << y.t << std::endl; 
} 
0

मैं सिर्फ @maraguida उदाहरण के लिए कुछ और बातें जोड़ा इस कार्यक्रम से उम्मीद उत्पादन देता है। मैंने इसे अधिक कमरे में रखने के लिए प्रतिक्रिया के रूप में लिखा था। यह दिखाता है कि न केवल सदस्य कार्य, बल्कि स्थिर सदस्य कार्य और ऑपरेटरों को भी जोड़ा जा सकता है।

#include <iostream> 

union x 
{ 
    int  t; 
    float f; 

    int k()  { return t * 42;}; 
    static int static_k() { return 42;}; 

    float k_f() { return f * 42.0f;}; 

    unsigned char operator [](unsigned int); 
}; 

unsigned char x::operator [](unsigned int i) 
{ 
    if (i >= sizeof(x)) 
     return 0; 

    return ((unsigned char *)&t)[ i ]; 
} 

int main() 
{ 
    x y; 
    y.t = x::static_k(); 

    std::cout << "y.t\t= " << y.t << std::endl; 
    std::cout << "y.f\t= " << y.f << std::endl; 
    std::cout << "y.k()\t= " << y.k() << std::endl; 
    std::cout << "x::static_k()\t= " << x::static_k() << std::endl; 
    std::cout << "y.k_f()\t= " << y.k_f() << std::endl; 

    std::cout << "y[ 0 ]\t= " << (unsigned int)y[ 0 ] << std::endl; 
    std::cout << "y[ 1 ]\t= " << (unsigned int)y[ 1 ] << std::endl; 
    std::cout << "y[ 2 ]\t= " << (unsigned int)y[ 2 ] << std::endl; 
    std::cout << "y[ 3 ]\t= " << (unsigned int)y[ 3 ] << std::endl; 
} 

यह साथ संकलित किया जा सकता: जी ++ -Wall union_func.cpp -ओ union_func

उत्पादन होता है:

$ ./union_func 
y.t  = 42 
y.f  = 5.88545e-44 
y.k() = 1764 
x::static_k() = 42 
y.k_f()  = 2.47189e-42 
y[ 0 ] = 42 
y[ 1 ] = 0 
y[ 2 ] = 0 
y[ 3 ] = 0 

आप, उदाहरण के लिए, एक रूपांतरण ऑपरेटर दूसरे करने के लिए रख सकते हैं आपकी आवश्यकता का प्रकार, अगर यह आपकी ज़रूरत को समझ में आता है।

10

तुम भी एक टेम्पलेट संघ बना सकते हैं:

template <typename T> 
union Foo { 
public: 
    Foo() {} 
    Foo(const T& value) : _val(value) {} 

    const char* data() const { 
    return _tab; 
    } 

    std::size_t size() const { 
    return sizeof(T); 
    } 

    char operator[](unsigned int index) const { 
     return _tab[index]; 
    } 

private: 
    T _val; 
    char _tab[sizeof(T)]; 
} 
1

union एक सी संरचना है, और सी ++ प्रकार के साथ अच्छी तरह से काम नहीं करता है (वहाँ चेतावनियां की एक संख्या वास्तव में कर रहे हैं)। हालांकि पहले से ही एक सी ++ समकक्ष मौजूद है, जो प्रभावी ढंग से सभी सी ++ वर्गों और उपयोगकर्ता परिभाषित वर्गों के साथ काम करता है और संघ से भी सुरक्षित है!

देखें Boost.Variant!

आप एक boost::variant<std::string, Foo, char> परिभाषित कर सकते हैं और यह सुनिश्चित करें कि बनाती हूँ:

  • कि उचित निर्माता/नाशक/असाइनमेंट ऑपरेटर चलाया जाता है, जरूरत पड़ने पर
  • है कि आप केवल नवीनतम मूल्य कि
  • स्थापित किया गया था का उपयोग

और यह भी साथ उत्कृष्ट आता है: boost::static_visitor<Result> जो मान लीजिए कि आप अपने प्रकार की परवाह किए बिना संघ पर एक विधि लागू करते हैं और चेतावनी देने के लिए जाँच संकलन समय प्रदान करते हैं जब भी आप संभव में से एक भूल गए प्रकार!

class MyVisitor: boost::static_visitor<int> 
{ 
public: 
    int operator()(std::string const& s) const { 
    return boost::lexical_cast<int>(s); 
    } 

    int operator()(Foo const& f) const { return f.getAsInt(); } 

    int operator()(char c) const { return c; } 
}; 

typedef boost::variant<std::string, Foo, char> MyVariant; 

int main(int argc, char* argv[]) { 
    MyVariant v; // the std::string is constructed 

    if (argc % 2) { v = Foo(4); } 
    if (argc % 3) { v = argv[1][0]; } 
    if (argc % 5) { v = argv[1]; } 

    std::cout << boost::apply_visitor(MyVisitor(), v) << '\n'; 
    return 0; 
} 

भी ... यह उतना प्रभावशाली (तेज) एक union के रूप में है, और किसी भी गतिशील लुक-अप Boost.Any चाहेंगे शामिल नहीं है।

संबंधित मुद्दे