Eclipse C ++项目不构建:构造函数析构问题 [英] Eclipse C++ project not building: Constructor Destructor Issue

查看:157
本文介绍了Eclipse C ++项目不构建:构造函数析构问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个头文件中的所有类定义:ModelModule.h。我已经提供了该文件的示例代码,在这里我已经声明了2个类及其成员函数:

  #pragma once 

#if!defined(MODELMODULE_H)
#define MODELMODULE_H


//所需的头文件

class CModelModule ;
class COrdProbitMM;

class CModelModule
//所有类型的建模模块的虚拟基类
{
friend class CSimCoordinator;
friend class CHouseholdCoordinator;
friend class CGenericHousehold;

public:
CModelModule(void);
〜CModelModule(void);

protected:
std :: string m_Label;
std :: vector< int> m_AvailEndAttr
void GetVarValues(std :: vector< int>& std :: vector< double>&);


public:


virtual void Configure(void){};
virtual void loadXmlString(xmlNodePtr pXmlNode,xmlDocPtr pXmlDoc,xmlChar * con);
virtual void SaveXml(std :: ofstream& fout){};

double mrand(void);
double UniformRand(); //返回一个U [0,1]随机数
double StdNormalRand(); // returns a N(0,1)random number
};

class COrdProbitMM:public CModelModule
//类表示有序概率模型
{
friend class CSimCoordinator;
friend class CHouseholdCoordinator;
friend class CMMRunner;

public:
COrdProbitMM(CSimCoordinator& simcord,std :: string& sLabel);
COrdProbitMM(CSimCoordinator& simcord,std :: string& sLabel,int nAlts);
〜COrdProbitMM(void);

private:

int m_Max_nAlts;
std :: vector< double> m_Thresholds;

public:
void Configure(void);
void copyConfigure(COrdProbitMM * that);

int Run(CHouseholdObject *);
int Run(CPersonObject *);


void loadXmlString(xmlNodePtr pConfNode,xmlDocPtr pXmlDoc,xmlChar * con);

private:
int Run(void);
}

现在函数定义已经在.cpp文件中给出:ModelModule.cpp。注意:已包含头文件

  #includeModelModule.h
//其他头文件

//这里定义的所有其他函数的代码

//下面给出了如何定义构造函数和析构函数的代码

COrdProbitMM :: 〜COrdProbitMM(void)
{
}

CModelModule :: CModelModule(void)
{
}

CModelModule: :〜CModelModule(void)
{
}

的任何句法错误。但是,当我构建代码,我得到错误make: * [ProjectName] Error1。在检查控制台时,我发现显示以下内容:

 构建目标:项目名称
调用:GCC C ++链接器
g ++ -oXYZ./src/XYZ.o ./src/DataCache\ -\ Copy.o ./src/DataCache.o ./src/DataCoordinator.o ./src/DataObject.o ./src/HouseholdCoordinator.o ./src/
LinearEquation.o ./src/MMRunner.o ./src/MainFrm.o ./src/ModelModule.o ./src/SimCoordinator.o ./src/ main.o -lxml2 -lsqlite3

./src/ModelModule.o:在函数`CModelModule :: CModelModule()'中:
ModelModule.cpp :(。text._ZN12CModelModuleC2Ev [CModelModule: :CModelModule()] + 0xd):未定义引用`vtable for CModelModule'
./src/ModelModule.o:在函数`CModelModule ::〜CModelModule()':
ModelModule.cpp :() .text._ZN12CModelModuleD2Ev [CModelModule ::〜CModelModule()] + 0xd):未定义引用`vtable for CModelModule'

./src/ModelModule.o:(.rodata._ZTI12COrdProbitMM[typeinfo for COrdProbitMM ] + 0x8):未定义引用`typeinfo for CModelModule'

collect2:ld返回1退出状态
make:*** [项目名称]错误1

**** Build Finished ****

我检查了这个论坛的vtable错误,它被提到的问题是当我们声明一个构造函数/析构函数但从未定义它。但是在这种情况下似乎不是一个问题,因为它在ModelModule.cpp中显式完成。似乎有一些非常基本的,在这里正在滑我的注意。




  • 我失踪了什么?

  • 你能告诉我什么是虚函数又是怎么造成错误的呢?


解决方案 div>

根本原因:

您会得到错误,因为C ++标准强制要求类的所有虚方法必须具有 [#1] 的定义。



解决方案:

为所有虚拟方法或使它们为纯 virtual



说明: $ b在这种情况下由gcc生成的错误最多是错误导向。以下是 示例计划 ,说明您遇到的问题:

  class MyClass 
{
public:
virtual void doSomething(){}
virtual void doSomethingMore();
}

int main()
{
MyClass obj;
obj.doSomething();
obj.doSomethingMore();
return 0;
}

编译信息:



< blockquote>

/home/4VqWl0/ccMjLi2V.o:在函数 main'中:

prog.cpp :(。text + 0x19):undefined vtable for MyClass

prog.cpp :(。text + 0x1e):未定义的引用
MyClass :: doSomethingMore )'

collect2:ld退回1退出状态


正如您所看到的,GCC在报告此错误特殊类型的问题。



是否以某种方式与构造函数和析构函数链接?

strong> gcc faq 还可以:


ISO C ++标准规定必须定义非纯虚拟类的所有虚方法,但不需要对违反此规则的任何诊断 [class.virtual] / 8 。基于这个假设,GCC将仅在定义其第一个这样的非内联方法的翻译单元中发出隐式定义的构造函数,赋值运算符,析构函数和虚表。



因此,如果你没有定义这个特定的方法,链接器可能会抱怨缺少明显不相关的符号的定义。不幸的是,为了改进此错误消息,可能需要更改链接器,但这并不总是可以完成。



解决方案是确保所有定义不纯的虚拟方法。注意,即使它被声明为纯虚拟 [class.dtor] / 7

$

$


良好阅读:



这是什么意思,虚拟表是未解决的外部?






[#1] C ++ 03 Standard:10.3 Virtual functions [class.virtual] p>


在类中声明的虚函数应在该类中定义或声明为纯(10.4)但不需要诊断(3.2)。



I have all the class definitions in a header file: ModelModule.h. I have provided the sample code for that file below where I have given the declaration of 2 classes and its member functions:

#pragma once

#if !defined( MODELMODULE_H )
#define MODELMODULE_H


//Required header files

class CModelModule;
class COrdProbitMM;

class CModelModule
// virtual base class for all types of modeling modules
{
    friend class CSimCoordinator;
    friend class CHouseholdCoordinator;
    friend class CGenericHousehold;

    public:
        CModelModule(void);
        ~CModelModule(void);

    protected:
        std::string         m_Label;        
        std::vector<int>        m_AvailEndAttr;     
        void GetVarValues(std::vector<int>&, std::vector<double> &);


    public:


        virtual void    Configure(void){};
        virtual void loadXmlString(xmlNodePtr pXmlNode, xmlDocPtr pXmlDoc, xmlChar * con);
        virtual void    SaveXml(std::ofstream& fout){};

        double mrand(void); 
        double UniformRand ();          // returns a U[0,1] random number 
        double StdNormalRand ();        // returns a N(0,1) random number
};

class COrdProbitMM : public CModelModule
// Class represent the ordered-probit models
{
    friend class CSimCoordinator;
    friend class CHouseholdCoordinator;
    friend class CMMRunner;

    public:
        COrdProbitMM(CSimCoordinator& simcord, std::string& sLabel);
        COrdProbitMM(CSimCoordinator& simcord, std::string& sLabel, int nAlts);
        ~COrdProbitMM(void);

    private: 

        int             m_Max_nAlts;    
        std::vector<double>     m_Thresholds;   

    public:
        void    Configure(void);
        void    copyConfigure(COrdProbitMM* that);

        int  Run(CHouseholdObject*);
        int  Run(CPersonObject*);


        void loadXmlString(xmlNodePtr pConfNode,  xmlDocPtr pXmlDoc, xmlChar* con);

    private:
        int     Run(void);
};  

Now the function definitions has been given in a .cpp file: ModelModule.cpp. Note: The header file has been included

#include "ModelModule.h"
//Other header files

//Code for all the other functions defined here

//Given below are the code for how the constructors and destructors are defined

COrdProbitMM::~COrdProbitMM(void)
{
}

CModelModule::CModelModule(void)
{
}

CModelModule::~CModelModule(void)
{   
}

I have rid the code of any syntactic error. However when I build the code I get the error make: *[ProjectName] Error1. On inspecting the console I find the following being displayed:

Building target: Project Name
Invoking: GCC C++ Linker
g++  -o "XYZ"  ./src/XYZ.o ./src/DataCache\ -\ Copy.o ./src/DataCache.o ./src/DataCoordinator.o ./src/DataObject.o ./src/HouseholdCoordinator.o ./src/
LinearEquation.o ./src/MMRunner.o ./src/MainFrm.o ./src/ModelModule.o ./src/SimCoordinator.o ./src/main.o   -lxml2 -lsqlite3

./src/ModelModule.o: In function `CModelModule::CModelModule()':
ModelModule.cpp:(.text._ZN12CModelModuleC2Ev[CModelModule::CModelModule()]+0xd): undefined reference to `vtable for CModelModule'
./src/ModelModule.o: In function `CModelModule::~CModelModule()':
ModelModule.cpp:(.text._ZN12CModelModuleD2Ev[CModelModule::~CModelModule()]+0xd): undefined reference to `vtable for CModelModule'

./src/ModelModule.o:(.rodata._ZTI12COrdProbitMM[typeinfo for COrdProbitMM]+0x8): undefined reference to `typeinfo for CModelModule'

collect2: ld returned 1 exit status
make: *** [Project Name] Error 1

**** Build Finished ****

I checked out this forum for the vtable error and it was mentioned that the problem is when we declare a constructor/destructor but never define it. But that does not seem to be a problem in this case as it was explicitly done in ModelModule.cpp. There seems to be something very basic that is going on here that is slipping my attention.

  • What is it that I'm missing?
  • Can you tell me what is with the virtual function and how it caused the error to come?
  • Does it somehow link up with the constructor and destructor?

解决方案

Root Cause:
You get the error because the C++ Standard mandates that All virtual methods of a class except the pure virtual methods Must have a definition[#1].

Solution:
Either provide definitions to all your virtual methods or make them pure virtual.

Explanation:
The error generated by gcc in such scenarios is at best mis-leading. Here is a sample program which demonstrates the problem you have:

class MyClass
{
    public:
    virtual void doSomething() { }
    virtual void doSomethingMore();
};

int main()
{
    MyClass obj;
    obj.doSomething();
    obj.doSomethingMore();
    return 0;
}

compilation info:

/home/4VqWl0/ccMjLi2V.o: In function main':
prog.cpp:(.text+0x19): undefined reference to
vtable for MyClass.
prog.cpp:(.text+0x1e): undefined reference to
MyClass::doSomethingMore()'
collect2: ld returned 1 exit status

As you see GCC is notorious in reporting errors for this particular type of problem.

Does it somehow link up with the constructor and destructor?

The gcc faq doccuments it as well:

The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.

Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.

The solution is to ensure that all virtual methods that are not pure are defined. Note that a destructor must be defined even if it is declared pure-virtual [class.dtor]/7.

Good Read:

What does it mean that the "virtual table" is an unresolved external?


[#1]C++03 Standard: 10.3 Virtual functions [class.virtual]

A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).

这篇关于Eclipse C ++项目不构建:构造函数析构问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆