अपरिहार्य संदर्भ अपरिहार्य है


357

मेरा C ++ प्रोग्राम बनाते समय, मुझे त्रुटि संदेश मिल रहा है

अपरिहार्य संदर्भ 'व्यवहार्य ...

इस समस्या का कारण क्या है? मैं इसे कैसे ठीक करूं?


ऐसा होता है कि मुझे निम्न कोड के लिए त्रुटि मिल रही है (प्रश्न में वर्ग CGameModule है।) और मैं मेरे जीवन के लिए यह नहीं समझ सकता कि समस्या क्या है। सबसे पहले, मैंने सोचा कि यह एक आभासी कार्य को एक शरीर देने के लिए भूल से संबंधित था, लेकिन जहां तक ​​मैं समझता हूं, सब कुछ यहां है। वंशानुक्रम श्रृंखला थोड़ी लंबी है, लेकिन यहां संबंधित स्रोत कोड है। मुझे यकीन नहीं है कि मुझे कौन सी अन्य जानकारी प्रदान करनी चाहिए।

नोट: कंस्ट्रक्टर वह जगह है जहां यह त्रुटि हो रही है, ऐसा प्रतीत होता है।

मेरा कोड:

class CGameModule : public CDasherModule {
 public:
  CGameModule(Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
  : CDasherModule(pEventHandler, pSettingsStore, iID, 0, szName)
  { 
      g_pLogger->Log("Inside game module constructor");   
      m_pInterface = pInterface; 
  }

  virtual ~CGameModule() {};

  std::string GetTypedTarget();

  std::string GetUntypedTarget();

  bool DecorateView(CDasherView *pView) {
      //g_pLogger->Log("Decorating the view");
      return false;
  }

  void SetDasherModel(CDasherModel *pModel) { m_pModel = pModel; }


  virtual void HandleEvent(Dasher::CEvent *pEvent); 

 private:



  CDasherNode *pLastTypedNode;


  CDasherNode *pNextTargetNode;


  std::string m_sTargetString;


  size_t m_stCurrentStringPos;


  CDasherModel *m_pModel;


  CDasherInterfaceBase *m_pInterface;
};

इनहेरीट से ...

class CDasherModule;
typedef std::vector<CDasherModule*>::size_type ModuleID_t;

/// \ingroup Core
/// @{
class CDasherModule : public Dasher::CDasherComponent {
 public:
  CDasherModule(Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore, ModuleID_t iID, int iType, const char *szName);

  virtual ModuleID_t GetID();
  virtual void SetID(ModuleID_t);
  virtual int GetType();
  virtual const char *GetName();

  virtual bool GetSettings(SModuleSettings **pSettings, int *iCount) {
    return false;
  };

 private:
  ModuleID_t m_iID;
  int m_iType;
  const char *m_szName;
};

जो विरासत में मिला…।

namespace Dasher {
  class CEvent;
  class CEventHandler;
  class CDasherComponent;
};

/// \ingroup Core
/// @{
class Dasher::CDasherComponent {
 public:
  CDasherComponent(Dasher::CEventHandler* pEventHandler, CSettingsStore* pSettingsStore);
  virtual ~CDasherComponent();

  void InsertEvent(Dasher::CEvent * pEvent);
  virtual void HandleEvent(Dasher::CEvent * pEvent) {};

  bool GetBoolParameter(int iParameter) const;
  void SetBoolParameter(int iParameter, bool bValue) const;

  long GetLongParameter(int iParameter) const;
  void SetLongParameter(int iParameter, long lValue) const;

  std::string GetStringParameter(int iParameter) const;
  void        SetStringParameter(int iParameter, const std::string & sValue) const;

  ParameterType   GetParameterType(int iParameter) const;
  std::string     GetParameterName(int iParameter) const;

 protected:
  Dasher::CEventHandler *m_pEventHandler;
  CSettingsStore *m_pSettingsStore;
};
/// @}


#endif

कौन सा फ़ंक्शन "अपरिहार्य संदर्भ को व्यवहार्य ..." फेंक रहा है?
जे। पोलर

3
मैं पूरी तरह से चूक गया कि त्रुटि संदेश एक फ़ंक्शन निर्दिष्ट करता है। यह कंस्ट्रक्टर का होता है, इसलिए मैंने अपने क्लास का नाम देखा और कनेक्शन नहीं बनाया। इसलिए, कंस्ट्रक्टर इसे फेंक रहा है। मैं उस विवरण को अपनी मूल पोस्ट में जोड़ दूंगा।
रयानगॉन

3
यदि आपने एक नया उत्पन्न करने के लिए महत्वपूर्ण परिवर्तन (जैसे qmake -projectऔर फिर qmake) करने के बाद अपनी परियोजना फ़ाइलों का पुनर्निर्माण नहीं किया है Makefile, तो Qt का उपयोग करते समय त्रुटि का एक संभावित स्रोत है।
डेविड सी। रंकिन

@ DavidC.Rankin, एक अन्य Qt संबंधित समस्या यह है कि अगर फ़ाइल को Q_OBJECTबाहरी रूप से कॉपी किया जाता है, लेकिन अभी तक .pro फ़ाइल का हिस्सा नहीं है, तो हालांकि यह ठीक संकलन करता है, यह लिंक नहीं करता है। हमें .h/.cppसक्षम होने के लिए .pro फ़ाइल में उस फ़ाइल को जोड़ना होगा qmake
Iammilind

जवाबों:


420

जीसीसी पूछे जाने वाले प्रश्न उस पर एक प्रविष्टि है:

इसका समाधान यह सुनिश्चित करना है कि सभी वर्चुअल तरीके जो शुद्ध नहीं हैं, परिभाषित हैं। ध्यान दें कि एक विध्वंसक को तब भी परिभाषित किया जाना चाहिए, भले ही वह शुद्ध-आभासी [class.dtor] / 7 घोषित हो।


17
nm -C CGameModule.o | grep CGameModule::उन विधियों को सूचीबद्ध करेगा जो आपके संपूर्ण वर्ग कार्यान्वयन को मानते हुए तार्किक ऑब्जेक्ट फ़ाइल में जाती हैं। आप इसकी तुलना कर सकते हैं कि जो कुछ भी याद किया गया है, उसका पता लगाने के लिए वर्चुअल के रूप में परिभाषित किया गया है।
ट्रॉय डेनियल

132
एफएफएस, क्यों कंपाइलर उसके लिए जांच नहीं करता है और एक त्रुटि संदेश प्रिंट करता है?
लेनार होयट

20
जाहिर है, यह केवल लिंकर द्वारा खोजा जा सकता है, न कि संकलक द्वारा।
ज़ोफ़

2
मेरे मामले में हमारे पास सार वर्ग था जिसमें विनाशकारी कार्यान्वयन नहीं था। मुझे खाली कार्यान्वयन करना पड़ा ~ MyClass () {}
शेफ़ी गुर-आर्य

1
आप इस तरह की एक त्रुटि प्राप्त कर सकते हैं जब आप लिंक करने की कोशिश कर रहे ऑब्जेक्ट संग्रह (libxyz.a फ़ाइल) में गुम है: `objfilename के लिए व्यवहार्य 'के लिए अपरिभाषित संदर्भ
झोउ

162

इसके लायक क्या है, एक आभासी विध्वंसक पर शरीर को भूल जाना निम्नलिखित उत्पन्न करता है:

अपरिहार्य संदर्भ `CYourClass के लिए व्यवहार्य '।

मैं एक नोट जोड़ रहा हूं क्योंकि त्रुटि संदेश भ्रामक है। (यह gcc संस्करण 4.6.3 के साथ था।)


23
मुझे स्पष्ट रूप से अपने खाली आभासी विध्वंसक के शरीर को परिभाषा फ़ाइल (* .cc) में रखना था। हेडर में यह होने के बाद भी मुझे त्रुटि दे दी है।
पॉपकॉर्नकिंग

4
ध्यान दें कि एक बार जब मैंने वर्चुअल डिस्ट्रक्टर को कार्यान्वयन फ़ाइल में जोड़ा, तो जीसीसी ने मुझे वास्तविक त्रुटि बताई, जो दूसरे फ़ंक्शन पर एक लापता बॉडी थी।
मूडबूम

1
@PopcornKing मैंने एक ही मुद्दा देखा। ~Destructor = default;हेडर फ़ाइल में परिभाषित करने से भी मदद नहीं मिली। क्या जीसीसी के खिलाफ एक दस्तावेज बग दर्ज किया गया है?
आरडी

यह एक अलग मुद्दा हो सकता है, लेकिन मेरी समस्या सिर्फ एक गैर-आभासी विध्वंसक के लिए एक कार्यान्वयन नहीं थी (जो अद्वितीय / साझा पॉइंटर्स पर स्विच कर रहा था और इसे स्रोत फ़ाइल से हटा दिया गया था, लेकिन हेडर में "कार्यान्वयन" नहीं था )
स्वेनव्स

वर्चुअल डिस्ट्रक्टर के लिए खाली {} बॉडी जोड़ने से मेरी समस्या हल हो गई, त्रुटि से बचा गया।
बोगदान इयोनित्जा

56

इसलिए, मैंने इस मुद्दे का पता लगा लिया है और यह खराब तर्क का एक संयोजन था और स्वचालित / ऑटोटूलस की दुनिया से पूरी तरह परिचित नहीं था। मैं अपने Makefile.am टेम्पलेट में सही फ़ाइलों को जोड़ रहा था, लेकिन मुझे यकीन नहीं था कि हमारी निर्माण प्रक्रिया में कौन सा कदम वास्तव में मेकफाइल ही बना था। इसलिए, मैं एक पुराने मेकफाइल का संकलन कर रहा था, जिसे मेरी नई फाइलों के बारे में कोई पता नहीं था।

प्रतिक्रियाओं के लिए धन्यवाद और जीसीसी FAQ के लिए लिंक। मुझे यकीन है कि वास्तविक कारण के लिए होने वाली इस समस्या से बचने के लिए पढ़ना होगा।


43
संक्षेप में: .cpp अभी बिल्ड में शामिल नहीं किया गया था। त्रुटि संदेश वास्तव में भ्रामक है।
ऑफर्मो

67
Qt उपयोगकर्ताओं के लिए: यदि आप शीर्ष लेख को भूल जाते हैं तो आप यह त्रुटि प्राप्त कर सकते हैं।
क्रिस मॉरेल

8
मुझे लगता है कि आपको अलेक्जेंड्रे हम्ज़ के जवाब को स्वीकार करना चाहिए। इस त्रुटि को खोजने वाले लोगों को आपके बजाय उसके समाधान की सबसे अधिक संभावना होगी।
टिम

13
-1 यह आपकी समस्या का समाधान हो सकता है, लेकिन यह मूल प्रश्न का उत्तर नहीं है। सही उत्तर बस इतना है कि आपने आवश्यक प्रतीकों के साथ एक ऑब्जेक्ट फ़ाइल प्रदान नहीं की है। आप उन्हें प्रदान करने में असफल क्यों हुए यह एक और कहानी है।
वाल्टर

12
@Walter: वास्तव में यह सटीक उत्तर था जिसकी मुझे तलाश थी। अन्य स्पष्ट हैं, और इस प्रकार अनहेल्दी हैं।
एडगर बोनट

50

यदि आप Qt का उपयोग कर रहे हैं, तो पुन: प्रयास करें qmake। यदि यह त्रुटि विजेट की कक्षा में है, तो क्यूमेक यह नोटिस करने में विफल हो सकता है कि यूआई वर्ग की वाइबर पुनर्जीवित होनी चाहिए। यह मेरे लिए मुद्दा तय किया।


2
मैं बस के रूप में अच्छी तरह से काम करने के साथ पूरे फ़ोल्डर को नष्ट कर दिया।
टॉम ज़ातो -

यह qmakeमेरे लिए अद्वितीय नहीं है , मेरे पास भी ऐसा ही था cmake। समस्या का एक हिस्सा यह हो सकता है कि दोनों टूल में हेडर फ़ाइलों के साथ एक समस्या है, जो जरूरत पड़ने पर हमेशा पुनर्निर्माण को ट्रिगर नहीं कर सकता है।
15 अक्टूबर को MSalters

2
सोचा "पुनर्निर्माण" फिर से स्वचालित रूप से ... स्पष्ट रूप से नहीं। मैंने आपके सुझाव पर "रन क्यूमेक" किया, फिर "पुनर्निर्माण" और इसने मेरी समस्या को ठीक कर दिया।
यानो

45

निम्न स्थिति के कारण व्यवहार्य होने का अपरिभाषित संदर्भ भी हो सकता है। बस यह प्रयास करें:

कक्षा एक में शामिल हैं:

virtual void functionA(parameters)=0; 
virtual void functionB(parameters);

कक्षा बी में शामिल हैं:

  1. उपरोक्त फ़ंक्शन के लिए परिभाषा।
  2. उपरोक्त फ़ंक्शन के लिए परिभाषा।

क्लास सी कंटेस्टेंट्स: अब आप एक क्लास सी लिख रहे हैं जिसमें आप इसे क्लास ए से निकालेंगे।

अब यदि आप संकलन करने का प्रयास करते हैं तो आपको कक्षा सी के लिए त्रुटि के रूप में अपरिहार्य संदर्भ मिलेगा।

कारण:

functionAको शुद्ध आभासी के रूप में परिभाषित किया गया है और कक्षा बी में इसकी परिभाषा functionBको आभासी के रूप में परिभाषित किया गया है (NOT PURE VIRTUAL) इसलिए यह कक्षा A में ही इसकी परिभाषा खोजने की कोशिश करता है लेकिन आपने कक्षा B में इसकी परिभाषा प्रदान की है।

समाधान:

  1. फ़ंक्शन बी को शुद्ध आभासी के रूप में बनाएं (यदि आपके पास उस तरह की आवश्यकता है) virtual void functionB(parameters) =0; (यह काम करता है यह परीक्षण किया गया है)
  2. कक्षा A में फ़ंक्शनबी के लिए परिभाषा को आभासी के रूप में रखते हुए प्रदान करें। (आशा है कि यह काम करता है क्योंकि मैंने यह कोशिश नहीं की)

@ ilya1725 आपका सुझाया हुआ संपादन केवल स्वरूपण को ठीक नहीं कर रहा है और आप जैसे हैं, आप उत्तर भी बदल रहे हैं, उदाहरण के लिए कि कक्षा C को A के बजाय B से लिया गया है, और आप दूसरा समाधान बदल रहे हैं। यह उत्तर को काफी हद तक बदल देता है। इन मामलों में, कृपया लेखक के बजाय एक टिप्पणी छोड़ दें। धन्यवाद!
फैबियो का कहना है कि मोनिका

@FabioTurati तब से किस वर्ग की श्रेणी विरासत में मिली है? वाक्य स्पष्ट नहीं है। इसके अलावा, "क्लास सी कॉन्टेंस:" का क्या अर्थ है?
ilya1725

@ ilya1725 यह उत्तर बहुत स्पष्ट नहीं है, और मैं इसे संपादित करने और इसे सुधारने के खिलाफ नहीं हूं। मैं जो कह रहा हूं, वह यह है कि आपके संपादन से उत्तर का अर्थ बदल जाता है, और यह बहुत अधिक बदलाव है। उम्मीद है, लेखक इसमें कदम रखेगा और स्पष्ट करेगा कि उसका क्या मतलब था (हालांकि वह लंबे समय से निष्क्रिय है)।
फैबियो का कहना है कि मोनिका

धन्यवाद! मेरे मामले में, मेरी पदानुक्रम में सिर्फ 2 कक्षाएं थीं। क्लास ए ने शुद्ध आभासी पद्धति घोषित की। क्लास बी की घोषणा में कहा गया है कि यह इस पद्धति को ओवरराइड करेगा, लेकिन मैंने अभी तक ओवरराइड विधि की परिभाषा नहीं लिखी थी।
निक डेसुलेनिर्स

44

मुझे बस यह त्रुटि मिली क्योंकि मेरी cpp फ़ाइल मेकफाइल में नहीं थी।


दरअसल, लगता है कि undefined reference to {function/class/struct}जब virtualचीजें शामिल होती हैं तो संदेश सामान्य से थोड़ा बदल जाता है। मुझे फेंक दिया।
कीथ एम

30

एक क्या है vtable?

यह जानने के लिए उपयोगी हो सकता है कि त्रुटि संदेश इसे ठीक करने की कोशिश करने से पहले क्या बात कर रहा है। मैं उच्च स्तर पर शुरू करूंगा, फिर कुछ और विवरणों पर काम करूंगा। इस तरह लोग vtables की अपनी समझ के साथ सहज होने के बाद आगे बढ़ सकते हैं। ... और अभी आगे जा रहे लोगों का एक झुंड चला जाता है। :) आसपास रहने वालों के लिए:

एक विटेबल मूल रूप से C ++ में बहुरूपता का सबसे आम कार्यान्वयन है । जब vtables का उपयोग किया जाता है, तो हर बहुरूपी वर्ग के कार्यक्रम में कहीं न कहीं एक व्यवहार्यता होती है; आप इसे कक्षा के एक (छिपे हुए) डेटा सदस्य के रूप में सोच सकते हैं । एक बहुरूपी वर्ग की प्रत्येक वस्तु अपने सबसे व्युत्पन्न वर्ग के लिए व्यवहार्य से जुड़ी होती है। इस एसोसिएशन की जाँच करके, कार्यक्रम अपने बहुरूपी जादू का काम कर सकता है। महत्वपूर्ण चेतावनी: एक व्यवहार्य एक कार्यान्वयन विस्तार है। यह C ++ मानक द्वारा अनिवार्य नहीं है, भले ही अधिकांश (सभी?) C ++ कंपाइलर पॉलीमॉर्फिक व्यवहार को लागू करने के लिए vtables का उपयोग करते हैं। जो विवरण मैं प्रस्तुत कर रहा हूं, वे या तो विशिष्ट हैं या उचित दृष्टिकोण हैं। कंपाइलरों को इससे भटकने दिया जाता है!static

प्रत्येक पॉलीमॉर्फिक ऑब्जेक्ट में ऑब्जेक्ट के सबसे व्युत्पन्न वर्ग (संभवतः अधिक जटिल मामलों में, एकाधिक पॉइंटर्स) के लिए व्यवहार्य के लिए एक (छिपा हुआ) सूचक होता है। पॉइंटर को देखकर, प्रोग्राम बता सकता है कि एक वस्तु का "वास्तविक" प्रकार क्या है (निर्माण के दौरान छोड़कर, लेकिन चलो उस विशेष को छोड़ दें)। उदाहरण के लिए, यदि किसी प्रकार की वस्तु Aवस्तुनिष्ठ की ओर इशारा नहीं करती है A, तो वह वस्तु वास्तव में किसी वस्तु से उप-वस्तु है A

" Vtable " नाम " v irtual फंक्शन टेबल " से आता है । यह एक तालिका है जो पॉइंटर्स टू (वर्चुअल) फ़ंक्शन को स्टोर करती है। एक कंपाइलर अपने कन्वेंशन को चुनता है कि टेबल कैसे रखी जाए; एक साधारण तरीका यह है कि वर्चुअल फ़ंक्शंस से गुज़रना है ताकि उन्हें कक्षा की परिभाषाओं में घोषित किया जा सके। जब एक वर्चुअल फ़ंक्शन को कॉल किया जाता है, तो प्रोग्राम ऑब्जेक्ट के पॉइंटर को एक विटेबल पर फॉलो करता है, वांछित फ़ंक्शन के साथ जुड़े एंट्री पर जाता है, फिर सही फ़ंक्शन को इनवॉइस करने के लिए संग्रहीत फ़ंक्शन पॉइंटर का उपयोग करता है। इस काम को करने के लिए कई तरकीबें हैं, लेकिन मैं यहाँ नहीं जाऊँगा।

कहाँ / कब vtableउत्पन्न होता है?

संकलक द्वारा एक विएबेट स्वचालित रूप से उत्पन्न होता है (कभी-कभी "उत्सर्जित" कहा जाता है)। एक संकलक हर अनुवाद इकाई में एक व्यवहार्य का उत्सर्जन कर सकता है जो एक बहुरूपी वर्ग परिभाषा देखता है, लेकिन यह आमतौर पर अनावश्यक टोकिल होगा। एक विकल्प ( जीसीसी द्वारा उपयोग किया जाता है , और शायद दूसरों के द्वारा) एक एकल अनुवाद इकाई को चुनना है जिसमें व्यवहार्य जगह है, इसी तरह आप एक एकल स्रोत फ़ाइल को चुनेंगे जिसमें क्लास के स्थैतिक डेटा सदस्यों को रखा जा सके। यदि यह चयन प्रक्रिया किसी भी अनुवाद इकाइयों को लेने में विफल रहती है, तो व्यवहार्य एक अपरिभाषित संदर्भ बन जाता है। इसलिए त्रुटि, जिसका संदेश विशेष रूप से स्पष्ट नहीं है।

इसी तरह, यदि चयन प्रक्रिया एक अनुवाद इकाई को चुनती है, लेकिन वह ऑब्जेक्ट फ़ाइल लिंकर को प्रदान नहीं की जाती है, तो विटेब एक अपरिभाषित संदर्भ बन जाता है। दुर्भाग्य से, त्रुटि संदेश इस मामले में उस मामले की तुलना में कम स्पष्ट हो सकता है जहां चयन प्रक्रिया विफल रही। (उत्तरदाताओं के लिए धन्यवाद जिन्होंने इस संभावना का उल्लेख किया है। मैं शायद इसे अन्यथा भूल गया होता।)

जीसीसी द्वारा उपयोग की जाने वाली चयन प्रक्रिया समझ में आती है यदि हम प्रत्येक वर्ग के लिए एक (एकल) स्रोत फ़ाइल को समर्पित करने की परंपरा से शुरू करते हैं जिसे इसके कार्यान्वयन के लिए एक की आवश्यकता होती है। उस स्रोत फ़ाइल को संकलित करते समय व्यवहार्यता का उत्सर्जन करना अच्छा होगा। चलो कि हमारे लक्ष्य को बुलाओ। हालाँकि, चयन प्रक्रिया को काम करने की आवश्यकता है भले ही इस परंपरा का पालन न किया जाए। इसलिए पूरी कक्षा के कार्यान्वयन की तलाश करने के बजाय, आइए कक्षा के किसी विशिष्ट सदस्य के कार्यान्वयन की तलाश करें। यदि परंपरा का पालन किया जाता है - और यदि वह सदस्य वास्तव में कार्यान्वित किया जाता है - तो यह लक्ष्य को प्राप्त करता है।

Gcc द्वारा चयनित सदस्य (और संभवतः अन्य संकलक द्वारा) पहला गैर-इनलाइन वर्चुअल फ़ंक्शन है जो शुद्ध वर्चुअल नहीं है। यदि आप उस भीड़ का हिस्सा हैं जो अन्य सदस्य कार्यों से पहले कंस्ट्रक्टर और विध्वंसक घोषित करता है, तो उस विध्वंसक के पास चुने जाने की अच्छी संभावना है। (आपने विध्वंसक को आभासी बनाने के लिए याद किया, ठीक है?) कुछ अपवाद हैं; मुझे उम्मीद है कि सबसे आम अपवाद तब होते हैं जब विध्वंसक के लिए एक इनलाइन परिभाषा प्रदान की जाती है और जब डिफ़ॉल्ट विध्वंसक का अनुरोध किया जाता है (" = default" का उपयोग करके )।

अचरज यह देख सकता है कि एक बहुरूपी वर्ग को अपने सभी आभासी कार्यों के लिए इनलाइन परिभाषाएँ प्रदान करने की अनुमति है। क्या चयन प्रक्रिया विफल होने का कारण नहीं है? यह पुराने कंपाइलरों में होता है। मैंने पढ़ा है कि नवीनतम संकलक ने इस स्थिति को संबोधित किया है, लेकिन मुझे प्रासंगिक संस्करण संख्याएं नहीं पता हैं। मैं इसे देखने की कोशिश कर सकता था, लेकिन इसके आस-पास या तो कोड करना आसान है या शिकायत करने वाले का इंतजार करना।

सारांश में, "अपरिहार्य संदर्भ के लिए व्यवहार्य" त्रुटि के तीन प्रमुख कारण हैं:

  1. एक सदस्य फ़ंक्शन इसकी परिभाषा याद कर रहा है।
  2. ऑब्जेक्ट फ़ाइल लिंक नहीं की जा रही है।
  3. सभी वर्चुअल फ़ंक्शंस में इनलाइन परिभाषाएँ होती हैं।

ये कारण स्वयं अपने आप में त्रुटि का कारण बनने के लिए अपर्याप्त हैं। बल्कि, ये वही हैं जिन्हें आप त्रुटि को हल करने के लिए संबोधित करेंगे। उम्मीद न करें कि इन स्थितियों में से एक को जानबूझकर पैदा करना निश्चित रूप से इस त्रुटि का उत्पादन करेगा; अन्य आवश्यकताएं हैं। उम्मीद करें कि इन स्थितियों को हल करने से यह त्रुटि हल हो जाएगी।

(ठीक है, यह प्रश्न पूछे जाने पर संख्या 3 पर्याप्त हो सकती है।)

त्रुटि कैसे ठीक करें?

आपका स्वागत है लोगों को छोड़ आगे बढ़ना! :)

  1. अपनी कक्षा की परिभाषा देखें। पहला गैर-इनलाइन वर्चुअल फ़ंक्शन खोजें जो शुद्ध वर्चुअल नहीं है (" = 0") और जिसकी परिभाषा आप प्रदान करते हैं (" = default") नहीं।
    • यदि ऐसा कोई फ़ंक्शन नहीं है, तो अपनी कक्षा को संशोधित करने का प्रयास करें ताकि एक हो। (त्रुटि संभवतः हल हो गई है।)
    • एक चेतावनी के लिए फिलिप थॉमस द्वारा उत्तर भी देखें ।
  2. उस फ़ंक्शन के लिए परिभाषा खोजें। यदि यह गायब है, तो इसे जोड़ें! (त्रुटि संभवतः हल हो गई है।)
  3. अपने लिंक कमांड की जाँच करें। यदि यह उस फ़ंक्शन की परिभाषा के साथ ऑब्जेक्ट फ़ाइल का उल्लेख नहीं करता है, तो इसे ठीक करें! (त्रुटि संभवतः हल हो गई है।)
  4. प्रत्येक वर्चुअल फ़ंक्शन के लिए चरण 2 और 3 को दोहराएं, फिर प्रत्येक गैर-वर्चुअल फ़ंक्शन के लिए, जब तक कि त्रुटि हल न हो जाए। यदि आप अभी भी अटके हुए हैं, तो प्रत्येक स्थिर डेटा सदस्य के लिए दोहराएं।

उदाहरण
क्या करना है, इसका विवरण अलग-अलग हो सकता है, और कभी-कभी अलग-अलग प्रश्नों में विभाजित होता है (जैसे कि एक अपरिभाषित संदर्भ / अनसुलझे बाहरी प्रतीक त्रुटि क्या है और मैं इसे कैसे ठीक करूं? )। मैं, हालांकि, एक विशिष्ट मामले में क्या करना है, इसका एक उदाहरण प्रदान कर सकता हूं जो नए प्रोग्रामर को परेशान कर सकता है।

चरण 1 में आपकी कक्षा को संशोधित करने का उल्लेख है ताकि इसमें एक निश्चित प्रकार का कार्य हो। यदि उस फ़ंक्शन का विवरण आपके सिर पर चला गया है, तो आप उस स्थिति में हो सकते हैं जिसे मैं संबोधित करना चाहता हूं। ध्यान रखें कि यह लक्ष्य को पूरा करने का एक तरीका है; यह एकमात्र तरीका नहीं है, और आपकी विशिष्ट स्थिति में आसानी से बेहतर तरीके हो सकते हैं। चलो अपनी कक्षा को बुलाओ A। क्या आपका विध्वंसक (आपकी कक्षा की परिभाषा में) घोषित किया गया है

virtual ~A() = default;

या

virtual ~A() {}

? यदि हां, तो दो चरण आपके विध्वंसक को उस प्रकार के फ़ंक्शन में बदल देंगे जो हम चाहते हैं। सबसे पहले, उस लाइन को बदल दें

virtual ~A();

दूसरा, निम्न लाइन को एक स्रोत फ़ाइल में रखें जो आपकी परियोजना का हिस्सा है (अधिमानतः वर्ग कार्यान्वयन के साथ फ़ाइल, यदि आपके पास एक है):

A::~A() {}

यह आपके (आभासी) विध्वंसक गैर-इनलाइन बनाता है और संकलक द्वारा उत्पन्न नहीं होता है। (अपनी कोड स्वरूपण शैली से बेहतर मिलान करने के लिए चीजों को संशोधित करने के लिए स्वतंत्र महसूस करें, जैसे कि फ़ंक्शन परिभाषा में हेडर टिप्पणी जोड़ना।)


ओह, ब्रावो! बहुत विस्तृत और बहुत अच्छी तरह से व्याख्या के लिए।
डेविड सी। रंकिन

इसे पढ़ने के लिए दूर तक स्क्रॉल करना पड़ा। उत्कृष्ट स्पष्टीकरण के लिए एक उत्थान है!
थॉमस

24

यहां विभिन्न उत्तरों में बहुत सारी अटकलें चल रही हैं। मैं नीचे एक काफी न्यूनतम कोड दूंगा जो इस त्रुटि को पुन: पेश करता है और समझाता है कि यह क्यों घट रहा है।

इस त्रुटि को पुन: उत्पन्न करने के लिए काफी न्यूनतम कोड

IBase.hpp

#pragma once

class IBase {
    public:
        virtual void action() = 0;
};

Derived.hpp

#pragma once

#include "IBase.hpp"

class Derived : public IBase {
    public:
        Derived(int a);
        void action() override;
};

Derived.cpp

#include "Derived.hpp"
Derived::Derived(int a) { }
void Derived::action() {}

myclass.cpp

#include <memory>
#include "Derived.hpp"

class MyClass {

    public:
        MyClass(std::shared_ptr<Derived> newInstance) : instance(newInstance) {

        }

        void doSomething() {
            instance->action();
        }

    private:
        std::shared_ptr<Derived> instance;
};

int main(int argc, char** argv) {
    Derived myInstance(5);
    MyClass c(std::make_shared<Derived>(myInstance));
    c.doSomething();
    return 0;
}

आप इस तरह से जीसीसी का उपयोग करके इसे संकलित कर सकते हैं:

g++ -std=c++11 -o a.out myclass.cpp Derived.cpp

अब आप = 0IBase.hpp में हटाकर त्रुटि को पुन: उत्पन्न कर सकते हैं । मुझे यह त्रुटि मिली:

~/.../catkin_ws$ g++ -std=c++11 -o /tmp/m.out /tmp/myclass.cpp /tmp/Derived.cpp
/tmp/cclLscB9.o: In function `IBase::IBase(IBase const&)':
myclass.cpp:(.text._ZN5IBaseC2ERKS_[_ZN5IBaseC5ERKS_]+0x13): undefined reference to `vtable for IBase'
/tmp/cc8Smvhm.o: In function `IBase::IBase()':
Derived.cpp:(.text._ZN5IBaseC2Ev[_ZN5IBaseC5Ev]+0xf): undefined reference to `vtable for IBase'
/tmp/cc8Smvhm.o:(.rodata._ZTI7Derived[_ZTI7Derived]+0x10): undefined reference to `typeinfo for IBase'
collect2: error: ld returned 1 exit status

व्याख्या

ध्यान दें कि उपरोक्त कोड को सफल होने के लिए संकलन के लिए किसी भी वर्चुअल डिस्ट्रक्टर्स, कंस्ट्रक्टर्स या किसी अन्य अतिरिक्त फ़ाइलों की आवश्यकता नहीं है (हालांकि आपको उन्हें करना चाहिए)।

इस त्रुटि को समझने का तरीका इस प्रकार है: लिंकर IBase के निर्माता की तलाश कर रहा है। यह व्युत्पन्न के निर्माता के लिए इसकी आवश्यकता होगी। हालाँकि जैसा कि डिबेड ने IBase से तरीकों को ओवरराइड किया है, इसमें इसके साथ व्यवहार्य है जो IBase को संदर्भित करेगा। जब लिंकर "IBase के लिए अपरिहार्य संदर्भ अपरिहार्य संदर्भ" कहता है, तो इसका मूल अर्थ यह है कि Derived का IBase के लिए संदर्भ है, लेकिन इसे देखने के लिए IBase का कोई संकलित ऑब्जेक्ट कोड नहीं मिल सकता है। तो लब्बोलुआब यह है कि वर्ग IBase के कार्यान्वयन के बिना घोषणाएं हैं। इसका मतलब है कि IBase में एक विधि को आभासी के रूप में घोषित किया गया है, लेकिन हम इसे शुद्ध आभासी के रूप में चिह्नित करना या इसकी परिभाषा प्रदान करना भूल गए।

बिदाई टिप

यदि बाकी सब विफल हो जाता है, तो इस त्रुटि को डीबग करने का एक तरीका न्यूनतम प्रोग्राम बनाना है जो संकलन करता है और फिर इसे बदलते रहें ताकि यह आपके इच्छित राज्य को मिल जाए। बीच-बीच में यह देखने के लिए संकलन करते रहें कि यह कब फेल होने लगे।

आरओएस और कैटकिन बिल्ड सिस्टम पर ध्यान दें

यदि आप cat के निर्माण प्रणाली का उपयोग करते हुए ROS में कक्षाओं के सेट के ऊपर संकलन कर रहे थे, तो आपको CMakeLists.txt में निम्न पंक्तियों की आवश्यकता होगी:

add_executable(myclass src/myclass.cpp src/Derived.cpp)
add_dependencies(myclass theseus_myclass_cpp)
target_link_libraries(myclass ${catkin_LIBRARIES})

पहली पंक्ति मूल रूप से कहती है कि हम एक निष्पादन योग्य नाम देना चाहते हैं जिसका नाम myclass है और इसे बनाने के लिए कोड को निम्न फ़ाइलों को पाया जा सकता है। इनमें से एक फाइल में मुख्य () होना चाहिए। ध्यान दें कि आपको CMakeLists.txt में कहीं भी .hpp फाइलें निर्दिष्ट नहीं करनी हैं। इसके अलावा आपको पुस्तकालय के रूप में Derived.cpp को निर्दिष्ट करने की आवश्यकता नहीं है।


18

मैं सिर्फ इस त्रुटि के लिए किसी अन्य कारण से भाग गया जिसे आप जांच सकते हैं।

बेस क्लास ने एक शुद्ध वर्चुअल फंक्शन को परिभाषित किया:

virtual int foo(int x = 0);

और उपवर्ग के पास था

int foo(int x) override;

समस्या टाइपो "=0"थी जो कोष्ठक के बाहर होने वाली थी:

virtual int foo(int x) = 0;

तो, यदि आप इसे बहुत दूर तक स्क्रॉल कर रहे हैं, तो संभवतः आपको इसका उत्तर नहीं मिला - यह कुछ और है।


12

यह काफी आसानी से हो सकता है यदि आप उस ऑब्जेक्ट फ़ाइल से लिंक करना भूल जाते हैं जिसमें परिभाषा है।


1
कृपया अपने उत्तर और संभावित सुधार के लिए कुछ और विवरण जोड़ें।
मोहित जैन

1
लिंक करने के लिए भूलना निर्देशों को बनाने के लिए जोड़ना भूल सकते हैं। मेरे मामले में, मेरी cpp फ़ाइल में सब कुछ पूरी तरह से 'परिभाषित' था, सिवाय इसके कि मैं cpp फ़ाइल को स्रोत सूची में जोड़ना भूल गया (मेरे CMakeLists.txt में, लेकिन वही अन्य बिल्ड सिस्टम जैसे कि .pro फ़ाइल में भी हो सकता है)। नतीजतन, सब कुछ संकलित हुआ और फिर मुझे लिंक समय पर त्रुटि मिली ...
ऋषि

@Mohit जैन ऑब्जेक्ट फ़ाइलों में लिंक कैसे करें पर्यावरण सेटअप और टूलिंग पर निर्भर करता है। दुर्भाग्य से एक व्यक्ति के लिए एक विशिष्ट निर्धारण दूसरे के लिए भिन्न हो सकता है (उदाहरण के लिए सीएमके बनाम मालिकाना उपकरण बनाम आईडीई बनाम आदि)
हज़ोक

11

GNU C ++ कंपाइलर को एक निर्णय करना होता है कि vtableआपको कई कंपाइल यूनिटों में फैले हुए ऑब्जेक्ट के वर्चुअल फ़ंक्शंस की परिभाषा कैसे करनी है (जैसे कि ऑब्जेक्ट्स की कुछ वर्चुअल फ़ंक्शंस परिभाषाएँ एक दूसरे में .cpp फ़ाइल दूसरों में हैं)। सीपीपी फ़ाइल, और इसी तरह)।

कंपाइलर vtableउसी जगह पर लगाने का विकल्प चुनता है, जहां पहले घोषित वर्चुअल फंक्शन को परिभाषित किया गया है।

अब यदि आप किसी कारण से ऑब्जेक्ट में घोषित उस पहले वर्चुअल फ़ंक्शन के लिए परिभाषा प्रदान करना भूल गए (या लिंकिंग चरण में संकलित ऑब्जेक्ट को जोड़ना भूल गए), तो आपको यह त्रुटि मिलेगी।

एक साइड इफेक्ट के रूप में, कृपया ध्यान दें कि केवल इस विशेष वर्चुअल फ़ंक्शन के लिए आपको पारंपरिक लिंकर त्रुटि नहीं मिलेगी, जैसे कि आप फ़ंक्शन फू गायब हैं


8

क्रॉस पोस्ट नहीं बल्कि यदि आप विरासत के साथ काम कर रहे हैं तो दूसरी गूगल हिट वह थी जो मैंने याद की थी, यानी। सभी आभासी तरीकों को परिभाषित किया जाना चाहिए।

जैसे कि:

virtual void fooBar() = 0;

जानकारी के लिए व्यवहार्य और वंशानुक्रम के लिए answare C ++ अपरिभाषित संदर्भ देखें। बस एहसास हुआ कि यह पहले से ही ऊपर उल्लेखित है, लेकिन बिल्ली यह किसी की मदद कर सकती है।


8

ठीक है, इसका समाधान यह है कि आप परिभाषा से चूक गए होंगे। वाइबर कंपाइलर त्रुटि से बचने के लिए नीचे दिया गया उदाहरण देखें:

// In the CGameModule.h

class CGameModule
{
public:
    CGameModule();
    ~CGameModule();

    virtual void init();
};

// In the CGameModule.cpp

#include "CGameModule.h"

CGameModule::CGameModule()
{

}

CGameModule::~CGameModule()
{

}

void CGameModule::init()    // Add the definition
{

}

7
  • क्या आप सुनिश्चित हैं कि CDasherComponentविनाशकारी के लिए एक शरीर है? यह निश्चित रूप से यहाँ नहीं है - सवाल यह है कि अगर यह .cc फ़ाइल में है।
  • एक शैली के दृष्टिकोण से, CDasherModuleस्पष्ट रूप से इसके विनाशकर्ता को परिभाषित करना चाहिए virtual
  • ऐसा लगता है कि अंत में (के बाद ) CGameModuleएक अतिरिक्त है ।}}; // for the class
  • है CGameModuleपुस्तकालयों को परिभाषित के खिलाफ जोड़ा जा रहा है CDasherModuleऔर CDasherComponent?

- हाँ, CDasherComponent की cpp में एक डिस्ट्रॉक्टर बॉडी है। मुझे लगा कि जब मैंने यह पोस्ट किया था तो यह .h में घोषित किया गया था। - विधिवत् नोट किया हुआ। - यह एक अतिरिक्त ब्रैकेट था जिसे मैंने गलती से जोड़ दिया था जब प्रलेखन छीन रहा था। - जहां तक ​​मेरी समझ है, हां। मैं एक स्वचालित फ़ाइल को संशोधित कर रहा हूं जिसे मैंने नहीं लिखा था, लेकिन मैं उन पैटर्न का पालन कर रहा हूं जो अन्य वर्गों के लिए समान श्रेणी से समान वंशानुक्रम पैटर्न के साथ काम करते हैं, इसलिए जब तक मैंने एक बेवकूफ गलती नहीं की है (पूरी तरह से संभव है) , मुझे नहीं लगता कि ऐसा है।
रयान

@RyanG: वर्ग परिभाषा में सभी आभासी फ़ंक्शन परिभाषाओं को स्थानांतरित करने का प्रयास करें। सुनिश्चित करें कि वे सभी वहां हैं और देखें कि क्या परिणाम बदलता है।
स्टीफन

5

शायद आभासी विध्वंसक लापता कारक योगदान दे रहा है?

virtual ~CDasherModule(){};

5

यह मेरे लिए पहला खोज परिणाम था, इसलिए मैंने सोचा कि मैं एक और चीज़ जोड़ना चाहूंगा: सुनिश्चित करें कि आभासी कार्यों की परिभाषा वास्तव में कक्षा में है। मेरे मामले में, मेरे पास यह था:

शीर्ष लेख फ़ाइल:

class A {
 public:
  virtual void foo() = 0;
};

class B : public A {
 public:
  void foo() override;
};

और मेरी .cc फ़ाइल में:

void foo() {
  ...
}

इसे पढ़ना चाहिए

void B::foo() {
}

3

शायद नहीं। निश्चित रूप ~CDasherModule() {}से गायब है।


3

यहाँ बहुत सारे उत्तर लेकिन उनमें से कोई भी ऐसा नहीं लगता था कि मेरी समस्या क्या है। मेरे पास निम्नलिखित थे:


class I {
    virtual void Foo()=0;
};

और एक अन्य फ़ाइल में (संकलन और लिंकिंग में शामिल)

class C : public I{
    void Foo() {
        //bar
    }
};

खैर यह काम नहीं किया और मुझे वह त्रुटि मिली जिसके बारे में हर कोई बात कर रहा है। इसे हल करने के लिए, मुझे फू की वास्तविक परिभाषा को इस तरह घोषित करना पड़ा:

class C : public I{
    void Foo();
};

C::Foo(){
   //bar
}

मैं कोई C ++ गुरु नहीं हूं इसलिए मैं यह नहीं समझा सकता कि यह अधिक सही क्यों है लेकिन इसने मेरे लिए समस्या को हल कर दिया है।


मैं कोई सी ++ गुरु नहीं हूं, लेकिन यह एक अतिरिक्त फाइल के साथ घोषणा और परिभाषा को एक ही फाइल में मिलाने से संबंधित है।
टेरी जी लॉबर

1
जब फ़ंक्शन परिभाषा आपकी वर्ग परिभाषा के अंदर थी, तो इसे "इनलाइन" घोषित किया गया था। उस समय, आपके सभी वर्चुअल फ़ंक्शंस इनबिल्ट थे। जब आपने फ़ंक्शन को वर्ग परिभाषा के बाहर स्थानांतरित किया, तो यह "इनलाइन" फ़ंक्शन नहीं था। चूंकि आपके पास एक गैर-इनबिल्ट वर्चुअल फ़ंक्शन था, इसलिए आपके कंपाइलर को पता था कि विएबेट को कहां फेंकना है। (एक अधिक गहन व्याख्या एक टिप्पणी में फिट नहीं होगी।)
JaMiT

3

इसलिए मैं Windows XP और MinGW कंपाइलर के साथ Qt का उपयोग कर रहा था और यह बात मुझे पागल कर रही थी।

मूल रूप से moc_xxx.cpp मेरे द्वारा जोड़े जाने पर भी खाली उत्पन्न होता था

Q_OBJECT

सब कुछ हटाने का कार्य आभासी, स्पष्ट और जो भी आपको लगता है कि काम नहीं करता है। अंत में मैंने लाइन से लाइन हटाना शुरू कर दिया और यह पता चला कि मेरे पास है

#ifdef something

फ़ाइल के आसपास। यहां तक ​​कि जब #ifdef सच था moc फ़ाइल उत्पन्न नहीं हुई थी।

इसलिए सभी #ifdefs हटाने से समस्या ठीक हो गई।

यह बात विंडोज और वीएस 2013 के साथ नहीं हो रही थी।


Q_OBJECT लाइन से टिप्पणी करते हुए एक सादे के साथ मेरी सरल परीक्षण ऐप का निर्माण किया g++ *.cpp ...। (त्वरित और गंदे कुछ की जरूरत है लेकिन क्यूमेक दुःख से भरा था।)
नाथन किड

2

यदि अन्य सभी विफल होते हैं, तो दोहराव की तलाश करें। जब तक मैं किसी अन्य पोस्ट में संदर्भ नहीं पढ़ता, मुझे कंस्ट्रक्टरों और विध्वंसकों के स्पष्ट प्रारंभिक संदर्भ द्वारा गलत समझा गया था। यह कोई भी अनसुलझी विधि है। मेरे मामले में, मुझे लगा कि मैंने घोषणा को बदल दिया है जो अनावश्यक रूप से परेशान कॉन्स्टेंट चार * xml का उपयोग करके पैरामीटर के रूप में char * xml का उपयोग करता है, लेकिन इसके बजाय, मैंने एक नया बनाया था और दूसरे को जगह में छोड़ दिया था।


2

इस त्रुटि के कारण के लिए बहुत सारी संभावनाएं बताई गई हैं, और मुझे यकीन है कि उनमें से कई त्रुटि का कारण हैं। मेरे मामले में, स्रोत फ़ाइल के दोहराव के कारण उसी वर्ग की एक और परिभाषा थी । यह फ़ाइल संकलित की गई थी, लेकिन लिंक नहीं की गई थी, इसलिए लिंकर इसे खोजने में असमर्थ होने के बारे में शिकायत कर रहा था।

संक्षेप में, मैं कहूंगा कि यदि आप कक्षा में काफी लंबे समय तक घूरते रहे हैं और यह नहीं देख सकते हैं कि वाक्यविन्यास की समस्या क्या हो सकती है, तो एक लापता फ़ाइल या डुप्लिकेट की गई फ़ाइल जैसी समस्याओं का निर्माण करें।


2

मेरे मामले में मैं क्यूटी का उपयोग कर रहा हूं और QObjectएक foo.cpp(नहीं .h) फ़ाइल में एक उपवर्ग को परिभाषित किया है । #include "foo.moc"के अंत में जोड़ना था foo.cpp


2

मुझे लगता है कि यह भी ध्यान देने योग्य है कि आप उस संदेश को भी प्राप्त करेंगे जब आप किसी भी वर्ग के ऑब्जेक्ट से लिंक करने का प्रयास करेंगे, जिसमें कम से कम एक आभासी विधि है और लिंकर फ़ाइल को नहीं ढूंढ सकता है। उदाहरण के लिए:

Foo.hpp:

class Foo
{
public:
    virtual void StartFooing();
};

Foo.cpp:

#include "Foo.hpp"

void Foo::StartFooing(){ //fooing }

इसके साथ संकलित:

g++ Foo.cpp -c

और main.cpp:

#include "Foo.hpp"

int main()
{
    Foo foo;
}

संकलित और इसके साथ जुड़ा:

g++ main.cpp -o main

हमारी पसंदीदा त्रुटि देता है:

/tmp/cclKnW0g.o: main': main.cpp:(.text+0x1a): undefined reference toफू 'कलेक्ट 2 के लिए फंक्शन वाइबल में: त्रुटि: ld 1% 1 स्टेटस स्थिति

मेरे अविवेकी बर्ताव से यह घटना:

  1. कंपाइल समय में प्रति कक्षा में Vtable बनाया जाता है

  2. लिंकर के पास वॉयटेबल तक पहुंच नहीं है जो फू में है


1

मुझे निम्न परिदृश्य में यह त्रुटि मिली

उस मामले पर विचार करें जहां आपने हेडर फ़ाइल में किसी वर्ग के सदस्य कार्यों के कार्यान्वयन को परिभाषित किया है। यह हेडर फ़ाइल एक निर्यात किया हुआ हेडर है (दूसरे शब्दों में, इसे कुछ सामान्य में कॉपी किया जा सकता है / सीधे आपके कोडबेस में शामिल किया जा सकता है)। अब आपने .cpp फ़ाइल में सदस्य कार्यों के कार्यान्वयन को अलग करने का निर्णय लिया है। आपके द्वारा .cpp पर क्रियान्वयन को अलग / स्थानांतरित करने के बाद, शीर्ष लेख फ़ाइल में अभी कक्षा के अंदर सदस्य कार्यों के प्रोटोटाइप हैं। उपरोक्त परिवर्तनों के बाद, यदि आप अपना कोडबेस बनाते हैं, तो आपको "अपरिहार्य संदर्भ" व्यवहार्य ... "त्रुटि प्राप्त हो सकती है।

इसे ठीक करने के लिए, निर्माण से पहले, सुनिश्चित करें कि आप हेडर फ़ाइल (जिसमें आपने परिवर्तन किए हैं) को सामान्य / निर्देशिका में शामिल कर हटाएं। यह भी सुनिश्चित करें कि आपने अपने .file को बदलने के लिए / नई फ़ाइल को जोड़ने के लिए बनाया है। आपके द्वारा बनाई गई नई .cpp फ़ाइल से बनाया गया है। जब आप इन चरणों को करते हैं तो कंपाइलर / लिंकर अब शिकायत नहीं करेगा।


अजीब। यदि किसी शीर्ष लेख को कहीं और कॉपी किया जाना है, तो बिल्ड सिस्टम को मूल रूप में संशोधित होते ही कॉपी को अपडेट करना चाहिए, और किसी अन्य फ़ाइल में शामिल किए जाने से पहले। यदि आपको इसे मैन्युअल रूप से करना है तो आपको खराब कर दिया जाता है।
ऑफर्मो

1

मुझे उन स्थितियों में इस प्रकार की त्रुटि मिली, जब मैं एक वस्तु को लिंक करने की कोशिश कर रहा था, जब मुझे एक बग मिला, जिसने ऑब्जेक्ट को संग्रह में जोड़ा जा रहा रोका।

कहो मेरे पास libXYZ.a है जो माना जाता है कि int में bioseq.o है लेकिन ऐसा नहीं है।

मुझे एक त्रुटि मिली:

combineseq.cpp:(.text+0xabc): undefined reference to `vtable for bioseq'

यह उपरोक्त सभी से अलग है। मैं इस अनुपलब्ध वस्तु को पुरालेख समस्या में कहूँगा।


0

यह भी संभव है कि आपको एक संदेश प्राप्त हो

SomeClassToTest.host.o: In function `class1::class1(std::string const&)':
class1.hpp:114: undefined reference to `vtable for class1'
SomeClassToTest.host.o: In function `class1::~class1()':
class1.hpp:119: undefined reference to `vtable for class1'
collect2: error: ld returned 1 exit status
[link] FAILED: 'g++' '-o' 'stage/tests/SomeClassToTest' 'object/tests/SomeClassToTest.host.o' 'object/tests/FakeClass1.SomeClassToTest.host.o'

यदि आप एक क्लास FakeClass1 के वर्चुअल फंक्शन को परिभाषित करना भूल जाते हैं, तो आप किसी अन्य क्लास SomeClass के लिए यूनिट टेस्ट लिंक करने की कोशिश कर रहे हैं।

//class declaration in class1.h
class class1
{
    public:
    class1()
    {
    }
    virtual ~class1()
    {
    }
    virtual void ForgottenFunc();
};

तथा

//class definition in FakeClass1.h
//...
//void ForgottenFunc() {} is missing here

इस मामले में मेरा सुझाव है कि आप कक्षा 1 के लिए एक बार फिर से अपने नकली की जाँच करें। आप शायद पाएंगे कि आप ForgottenFuncअपनी फर्जी क्लास में वर्चुअल फंक्शन को परिभाषित करना भूल गए हैं ।


0

मुझे यह त्रुटि तब मिली जब मैंने एक मौजूदा स्रोत / हेडर जोड़ी में दूसरी श्रेणी जोड़ी। एक ही .h फ़ाइल में दो क्लास हेडर, और एक ही .cpp फ़ाइल में दो वर्गों के लिए फ़ंक्शन परिभाषाएँ।

मैंने इसे सफलतापूर्वक पहले किया है, उन कक्षाओं के साथ जो एक साथ मिलकर काम करने के लिए हैं, लेकिन स्पष्ट रूप से कुछ इस बार मुझे पसंद नहीं आया। अभी भी पता नहीं क्या है, लेकिन उन्हें संकलन इकाई प्रति एक वर्ग में विभाजित करके इसे ठीक किया।


असफल प्रयास:

_gui_icondata.h:

#ifndef ICONDATA_H
#define ICONDATA_H

class Data;
class QPixmap;

class IconData
{
public:
    explicit IconData();
    virtual ~IconData();

    virtual void setData(Data* newData);
    Data* getData() const;
    virtual const QPixmap* getPixmap() const = 0;

    void toggleSelected();
    void toggleMirror();
    virtual void updateSelection() = 0;
    virtual void updatePixmap(const QPixmap* pixmap) = 0;

protected:
    Data* myData;
};

//--------------------------------------------------------------------------------------------------

#include "_gui_icon.h"

class IconWithData : public Icon, public IconData
{
    Q_OBJECT
public:
    explicit IconWithData(QWidget* parent);
    virtual ~IconWithData();

    virtual const QPixmap* getPixmap() const;
    virtual void updateSelection();
    virtual void updatePixmap(const QPixmap* pixmap);

signals:

public slots:
};

#endif // ICONDATA_H

_gui_icondata.cpp:

#include "_gui_icondata.h"

#include "data.h"

IconData::IconData()
{
    myData = 0;
}

IconData::~IconData()
{
    if(myData)
    {
        myData->removeIcon(this);
    }
    //don't need to clean up any more; this entire object is going away anyway
}

void IconData::setData(Data* newData)
{
    if(myData)
    {
        myData->removeIcon(this);
    }
    myData = newData;
    if(myData)
    {
        myData->addIcon(this, false);
    }
    updateSelection();
}

Data* IconData::getData() const
{
    return myData;
}

void IconData::toggleSelected()
{
    if(!myData)
    {
        return;
    }

    myData->setSelected(!myData->getSelected());
    updateSelection();
}

void IconData::toggleMirror()
{
    if(!myData)
    {
        return;
    }

    myData->setMirrored(!myData->getMirrored());
    updateSelection();
}

//--------------------------------------------------------------------------------------------------

IconWithData::IconWithData(QWidget* parent) :
    Icon(parent), IconData()
{
}

IconWithData::~IconWithData()
{
}

const QPixmap* IconWithData::getPixmap() const
{
    return Icon::pixmap();
}

void IconWithData::updateSelection()
{
}

void IconWithData::updatePixmap(const QPixmap* pixmap)
{
    Icon::setPixmap(pixmap, true, true);
}

फिर से, एक नया स्रोत / हेडर जोड़ी जोड़कर और "अभी काम किया" में IconWithData वर्ग शब्दशः को काटना / चिपकाना।


0

मेरा मामला एक मूर्खतापूर्ण था, मुझे गलती से और अनुमान लगाने के "बाद एक अतिरिक्त मिला था #include?

undefined reference to vtable!

मैं अपने सिर और चेहरे को खरोंच कर रहा हूं और घंटों तक आभासी कार्यों के लिए टिप्पणी करता हूं कि यह देखने के लिए कि क्या कुछ बदल गया है, और अंत में अतिरिक्त को हटाकर " , सब कुछ तय हो गया! इस तरह की चीजों को वास्तव में संकलन त्रुटि नहीं लिंक त्रुटि में परिणाम की आवश्यकता है।

अतिरिक्त रूप से ", मेरा मतलब है:

#include "SomeHeader.h""

0

मेरे मामले में, मेरे पास एक आधार वर्ग था जिसका नाम व्यक्ति और दो व्युत्पन्न वर्ग थे, जिसका नाम छात्र और प्रोफेसर था।

मेरा कार्यक्रम कैसे तय हो गया था, 1. मैं बनाया सभी कार्यों आधार वर्ग में Pure Virtual. 2. मैं इस्तेमाल किया सब आभासी विनाशकर्ता के रूप मेंdefault ones.


-3

मुझे यह त्रुटि केवल इसलिए मिली क्योंकि एक रचनाकार तर्क का नाम हेडर फ़ाइल और कार्यान्वयन फ़ाइल में भिन्न था। कंस्ट्रक्टर हस्ताक्षर है

PointSet (const PointSet & pset, Parent * parent = 0);

और जो मैंने कार्यान्वयन में लिखा था, उसके साथ शुरू हुआ

PointSet (const PointSet & pest, Parent * parent)

इस प्रकार मैंने "कीट" के स्थान पर आकस्मिक रूप से "कीट" लगा दिया। कंपाइलर इस एक और दो अन्य कंस्ट्रक्टर के बारे में शिकायत कर रहा था जिसमें कोई त्रुटि नहीं थी। मैं Ubuntu के तहत g ++ संस्करण 4.9.1 का उपयोग कर रहा हूं। और इस व्युत्पन्न वर्ग में एक आभासी विध्वंसक को परिभाषित करने से कोई अंतर नहीं पड़ा (इसे आधार वर्ग में परिभाषित किया गया है)। अगर मैं हेडर फ़ाइल में कंस्ट्रक्टर्स बॉडीज़ को पेस्ट नहीं करता, तो मुझे यह बग कभी नहीं मिलता।


7
इससे कोई फर्क नहीं पड़ेगा, आपके पास त्रुटि कहीं और होनी चाहिए और अनजाने में इसे ठीक कर दिया जाएगा।
MM
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.