2

ヘッダーファイルModelModule.hにすべてのクラス定義があります。そのファイルのサンプルコードを以下に示します。ここでは、2つのクラスとそのメンバー関数の宣言を示しています。

#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);
};  

これで、関数定義が.cppファイルModelModule.cppで指定されました。注:ヘッダーファイルはインクルードされています

#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)
{   
}

コードから構文エラーを取り除きました。ただし、コードをビルドすると、次のエラーが発生します。* [ProjectName]Error1。コンソールを調べると、次のように表示されています。

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 ****

このフォーラムでvtableエラーを確認しましたが、問題はコンストラクタ/デストラクタを宣言したが、定義しなかった場合であるとのことでした。ただし、ModelModule.cppで明示的に行われたため、この場合は問題にはならないようです。ここで起こっている非常に基本的なことが私の注意をそらしているようです。

  • 私が行方不明になっているのは何ですか?
  • 仮想関数とは何で、どのようにしてエラーが発生したのか教えてください。
  • それはどういうわけかコンストラクタとデストラクタとリンクしていますか?
4

1 に答える 1

3

根本原因: C ++標準では、純粋仮想メソッドを除くクラスのすべての仮想メソッドに定義[#1]が必要
である ことが義務付けられているため、エラーが発生します。

解決策:
すべてのメソッドに定義を提供するvirtualか、それらを純粋にしvirtualます。

説明:
このようなシナリオでgccによって生成されるエラーは、せいぜい誤解を招くものです。これがあなたが抱えている問題を示す サンプルプログラムです:

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

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

コンパイル情報:

/home/4VqWl0/ccMjLi2V.o:MyClassの関数vtableでMyClass :: doSomethingMore()' collect2:ldが1つの終了ステータスを返しました main':
prog.cpp:(.text+0x19): undefined reference to
.
prog.cpp:(.text+0x1e): undefined reference to

ご覧のとおり、GCCはこの特定のタイプの問題のエラーを報告することで有名です。

それはどういうわけかコンストラクタとデストラクタとリンクしていますか?

gccのよくある質問もそれを文書化しています:

ISO C ++標準では、純粋仮想ではないクラスのすべての仮想メソッドを定義する必要があると指定されていますが、このルールの違反に対する診断は必要ありません[class.virtual]/8。この仮定に基づいて、GCCは、暗黙的に定義されたコンストラクター、代入演算子、デストラクタ、および最初のそのような非インラインメソッドを定義する変換ユニット内のクラスの仮想テーブルのみを出力します。

したがって、この特定のメソッドを定義しなかった場合、リンカは明らかに無関係なシンボルの定義がないことについて不平を言う可能性があります。残念ながら、このエラーメッセージを改善するには、リンカーを変更する必要がある場合がありますが、これを常に実行できるとは限りません。

解決策は、純粋ではないすべての仮想メソッドが定義されていることを確認することです。純粋仮想として宣言されている場合でも、デストラクタを定義する必要があることに注意してください[class.dtor]/7

良い読み物:

「仮想テーブル」が未解決の外部であるとはどういう意味ですか?


[#1] C ++ 03標準:10.3仮想関数[class.virtual]

クラスで宣言された仮想関数は、そのクラスで定義されるか、純粋(10.4)として宣言されるか、またはその両方である必要があります。ただし、診断は必要ありません(3.2)。

于 2012-04-04T08:31:04.530 に答える