2012-01-03 13 views
15

मुझे हाल ही में कई कक्षाओं के लिंक विनिर्देश को बदलना पड़ा और एक समस्या में भाग गया। कक्षाओं में से दो में std::mapstd::unique_ptr के साथ मान प्रकार के रूप में std::map शामिल हैं। लिंकेज बदलने के बाद संकलक ने शिकायत शुरू कर दी "कक्षा में घोषित निजी सदस्य तक पहुंच नहीं सकते" std :: unique_ptr < _Ty> '' त्रुटियां।"निजी सदस्य तक नहीं पहुंच सकता है" त्रुटि केवल तब होती है जब कक्षा में निर्यात लिंक

कोई भी जानता है कि यह तब होता है जब निर्यात विनिर्देश की आपूर्ति की जाती है या कोई समाधान होता है?

नमूना कोड:

#include <map> 

struct SomeInterface 
{ 
    virtual ~SomeInterface() = 0; 
}; 


// This class compiles with no problems 
struct LocalClass 
{ 
    std::map<int, std::unique_ptr<SomeInterface>> mData; 
}; 

// This class fails to compile 
struct __declspec(dllexport) ExportedClass 
{ 
    std::map<int, std::unique_ptr<SomeInterface>> mData; 
}; 

संकलक उत्पादन:

c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(163): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 
     with 
     [ 
      _Ty=SomeInterface 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory(2347) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr' 
     with 
     [ 
      _Ty=SomeInterface 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(195) : see reference to function template instantiation 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base<const int&,_Ty2&>(_Other1,_Other2)' being compiled 
     with 
     [ 
      _Ty1=const int, 
      _Ty2=std::unique_ptr<SomeInterface>, 
      _Other1=const int &, 
      _Other2=std::unique_ptr<SomeInterface> & 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory(208) : see reference to function template instantiation 'std::pair<_Ty1,_Ty2>::pair<const _Kty,_Ty>(std::pair<_Ty1,_Ty2> &)' being compiled 
     with 
     [ 
      _Ty1=const int, 
      _Ty2=std::unique_ptr<SomeInterface>, 
      _Kty=int, 
      _Ty=std::unique_ptr<SomeInterface> 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory(280) : see reference to function template instantiation 'void std::allocator<_Ty>::construct<std::pair<_Ty1,_Ty2>&>(std::pair<_Ty1,_Ty2> *,_Other)' being compiled 
     with 
     [ 
      _Ty=std::pair<const int,std::unique_ptr<SomeInterface>>, 
      _Ty1=const int, 
      _Ty2=std::unique_ptr<SomeInterface>, 
      _Other=std::pair<const int,std::unique_ptr<SomeInterface>> & 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree(592) : see reference to function template instantiation 'void std::_Cons_val<std::allocator<_Ty>,_Ty,std::pair<_Ty1,_Ty2>&>(_Alloc &,std::pair<_Ty1,_Ty2> *,std::pair<_Ty1,_Ty2>)' being compiled 
     with 
     [ 
      _Ty=std::pair<const int,std::unique_ptr<SomeInterface>>, 
      _Ty1=const int, 
      _Ty2=std::unique_ptr<SomeInterface>, 
      _Alloc=std::allocator<std::pair<const int,std::unique_ptr<SomeInterface>>> 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree(1521) : see reference to function template instantiation 'std::_Tree_nod<_Traits>::_Node *std::_Tree_val<_Traits>::_Buynode<std::pair<_Ty1,_Ty2>&>(_Valty)' being compiled 
     with 
     [ 
      _Traits=std::_Tmap_traits<int,std::unique_ptr<SomeInterface>,std::less<int>,std::allocator<std::pair<const int,std::unique_ptr<SomeInterface>>>,false>, 
      _Ty1=const int, 
      _Ty2=std::unique_ptr<SomeInterface>, 
      _Valty=std::pair<const int,std::unique_ptr<SomeInterface>> & 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree(1516) : while compiling class template member function 'std::_Tree_nod<_Traits>::_Node *std::_Tree<_Traits>::_Copy(std::_Tree_nod<_Traits>::_Node *,std::_Tree_nod<_Traits>::_Node *)' 
     with 
     [ 
      _Traits=std::_Tmap_traits<int,std::unique_ptr<SomeInterface>,std::less<int>,std::allocator<std::pair<const int,std::unique_ptr<SomeInterface>>>,false> 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\map(81) : see reference to class template instantiation 'std::_Tree<_Traits>' being compiled 
     with 
     [ 
      _Traits=std::_Tmap_traits<int,std::unique_ptr<SomeInterface>,std::less<int>,std::allocator<std::pair<const int,std::unique_ptr<SomeInterface>>>,false> 
     ] 
     c:\projects\so\so\so.cpp(18) : see reference to class template instantiation 'std::map<_Kty,_Ty>' being compiled 
     with 
     [ 
      _Kty=int, 
      _Ty=std::unique_ptr<SomeInterface> 
     ] 
+2

कम से कम, यह एक पूरी तरह से मंच- और संकलक-विशिष्ट समस्या है। सी ++ में एक मानक एबीआई नहीं है, और * वर्ग * परिभाषा पर '__declspec (declexport)' के प्रभाव पूरी तरह से कंपाइलर तक हैं। –

उत्तर

22

त्रुटि दी गई है क्योंकि संकलक प्रतिलिपि बनाने के लिए कॉपी कन्स्ट्रक्टर और कॉपी असाइनमेंट ऑपरेटर नहीं बना सकता है। इसके लिए unique_ptr ऑब्जेक्ट्स की प्रतिलिपि बनाने की आवश्यकता होगी जिसमें कॉपी कन्स्ट्रक्टर नहीं हैं (वे चलने योग्य हैं लेकिन कॉपी करने योग्य नहीं हैं)।

सामान्य कक्षा के लिए त्रुटि नहीं दी गई है क्योंकि कॉपी कन्स्ट्रक्टर/असाइनमेंट वास्तव में कहीं भी उपयोग नहीं किया जाता है। हालांकि जब __declspec (dllexport) मौजूद होता है तो सभी कंपाइलर जेनरेट किए गए फ़ंक्शंस तत्काल होते हैं (यहां सही शब्दावली के बारे में निश्चित नहीं है लेकिन ऐसा कुछ :)।

struct __declspec(dllexport) ExportedClass 
{ 
    std::map<int, std::unique_ptr<SomeInterface>> mData; 
private: 
    ExportedClass(const ExportedClass&) {} 
    ExportedClass& operator=(const ExportedClass&) { return *this; } 
}; 
+1

यह टिकट है। NEET-ओ! –

+1

जब आप एक प्रकार का निर्यात करते हैं, तो संपूर्ण सार्वजनिक इंटरफ़ेस प्लस इनलाइन फ़ंक्शंस द्वारा उपयोग की जाने वाली किसी भी चीज़ को भी निर्यात किया जाना चाहिए। विवरण के लिए [चेतावनी C4251] (http://msdn.microsoft.com/en-us/library/esew7y1w.aspx) के लिए दस्तावेज़ देखें। –

+0

मुझे पहले से ही सी 4251 के बारे में पता है, हालांकि इसे उदाहरण कोड में संबोधित करना व्यर्थ अव्यवस्था होगा और मेरे प्रश्न के लिए अपरिवर्तनीय नहीं है। –

2

मैं एक लंबे समय पहले इस में भाग है, तो यह करने के लिए विवरण कुछ धुंधले हैं।

संक्षेप में जब आप एक वर्ग निर्यात करते हैं तो आपको सभी निहित वर्गों को भी सार्वजनिक रूप से निर्यात करना होता है या नहीं। आपके मामले में std::map और std::unique_ptr होगा। मुझे यकीन नहीं है कि मानक पुस्तकालयों में कक्षाएं यहां कैसे व्यवहार करती हैं, यह धुंधला हिस्सा है, लेकिन मुझे याद है कि इसमें समस्याएं थीं।

समाधान या तो उन वर्गों को निर्यात करना है या PIMPL कार्यान्वयन का उपयोग करना है (जो किसी भी तरह से निर्यात किए गए वर्गों के लिए एक अच्छा विचार है)।

+0

डीएलएल कक्षा इंटरफेस के लिए पीआईएमपीएल का उपयोग करना चीजों को बहुत आसान बनाता है :) – paulm

0

अक्सर एक 'std::move(iUniquePtr)' कहीं याद आ रही है:

एक तरीका यह त्रुटि को ठीक करने के लिए ExportedClass उन दो कार्यों को परिभाषित करने और उन्हें निजी के रूप में चिह्नित करने के लिए है।

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

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