0

chrono::engineのチュートリアルに従っている非常に単純なコードに問題がありますhttp://www.chronoengine.info/mediawiki/index.php/Demo_fourbarC++ プログラミングの経験があまりありません( Javaでの経験があるため)、C ++コードの古典的な構造に頭を悩ませるために、MyEventReceiver(チュートリアルのクラス)を別のファイル(MyEventReceiver.hおよびMyEventReceiver.cpp)で定義しようとしました。

これがコードのバージョンです

MyEventReceiver.h

#ifndef RECEIVER_H
#define RECEIVER_H

#include "physics/CHapidll.h"
#include "physics/CHsystem.h"
#include "irrlicht_interface/CHbodySceneNode.h"
#include "irrlicht_interface/CHbodySceneNodeTools.h"
#include "irrlicht_interface/CHdisplayTools.h"
#include "irrlicht_interface/CHirrWizard.h"
#include "core/CHrealtimeStep.h"

#include <irrlicht.h>


// Use the namespace of Chrono
using namespace chrono;

// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

class MyEventReceiver : public IEventReceiver
{
public:
    MyEventReceiver(ChSystem* asystem, IrrlichtDevice* adevice,     ChSharedPtr<ChLinkEngine> aengine);
    bool OnEvent(const SEvent& event);
    void setText_enginespeed(IGUIStaticText* _text_enginespeed);
    IGUIStaticText* getText_enginespeed();
private:
    IGUIStaticText* text_enginespeed;
    ChSystem*       msystem;
    IrrlichtDevice* mdevice;
    ChSharedPtr<ChLinkEngine> mengine;
};

#endif

MyEventReceiver.cppで次のように実装します

#include "MyEventReceiver.h"


// Constructor
MyEventReceiver::MyEventReceiver(ChSystem *asystem, IrrlichtDevice *adevice, ChSharedPtr<ChLinkEngine> aengine)
{
    // store pointer to physical system & other stuff
    // so we can tweak them by user keyboard
    msystem = asystem;
    mdevice = adevice;
    mengine = aengine;
}



bool MyEventReceiver::OnEvent(const SEvent& event)
{
    // check if user moved the sliders with mouse..
        if (event.EventType == EET_GUI_EVENT)
        {
            s32 id = event.GUIEvent.Caller->getID();
            IGUIEnvironment* env = mdevice->getGUIEnvironment();

            switch(event.GUIEvent.EventType)
            {
            case EGET_SCROLL_BAR_CHANGED:
                    if (id == 101) // id of 'engine speed' gui
                    {
                        s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
                        double newspeed = 10*(double)pos/100.0;

                        // set the speed into engine object
                        ChFunction_Const *spe_funct = dynamic_cast <ChFunction_Const*> (mengine->Get_spe_funct());
                        spe_funct->Set_yconst(newspeed);


                        // show speed as formatted text in interface screen
                        char message[50]; sprintf(message,"Engine speed: %g [rad/s]",newspeed);
                        text_enginespeed->setText(core::stringw(message).c_str());

                    }
            break;
            }

        }

        return false;
}


void MyEventReceiver::setText_enginespeed(IGUIStaticText* _text_enginespeed)
{
    text_enginespeed = _text_enginespeed;
}


IGUIStaticText* MyEventReceiver::getText_enginespeed()
{
    return text_enginespeed;
}

そしてMain_2.cppのメインファイル(私が空にした、それは私にコードの有無にかかわらず同じエラーを与えます-これは基本的に3DエンジンIrrlichtとchrono :: engineの衝突モデルからのいくつかの力学機能をセットアップするだけです)

#include "MyEventReceiver.h"

int main()
{
    return 0;
}

基本的に、コードはイベントレシーバーを定義するため、プログラムを実行した後、ユーザーはGUI操作を介してchrono :: engineおよびIrrlichtエンジンから構築された3D環境と対話できます。MyEventReceiver.hファイルで必要なすべてのライブラリと、必要なライブラリを定義します。名前空間

問題は、コンパイルされないことです(同じ#includeを使用し、1つのファイルで名前空間を使用して、別のプロジェクトで動作していたエンジンをすでにテストしていることに注意してください)、問題は構造に起因していると思いますヘッダーファイルの

私はそれらのエラーの行を取得しました

1>MyEventReceiver.obj : error LNK2005: "public: virtual bool __thiscall irr::scene::RTSCamera::OnEvent(struct irr::SEvent const &)" (?OnEvent@RTSCamera@scene@irr@@UAE_NABUSEvent@3@@Z) already defined in Main_2.obj
1>MyEventReceiver.obj : error LNK2005: "public: virtual void __thiscall irr::scene::RTSCamera::OnRegisterSceneNode(void)" (?OnRegisterSceneNode@RTSCamera@scene@irr@@UAEXXZ) already defined in Main_2.obj

など...(このように続きます)そして最後の間違い

1>C:\Users\****\Documents\Visual Studio 2010\Projects\TutorialChronoEngine\Debug\TutorialChronoEngine_2.exe : fatal error LNK1169: one or more multiply defined symbols found

Visual Studio 2010C++を使用しています。私は1つのグローバルソリューションを定義し、このソリューションのいくつかのプロジェクト(上記で書いたプログラムはとりわけ1つのプロジェクトです)は、かなり簡単に解決できるはずですが、実際には解決策を見つけることができません。詳細が必要な場合はお知らせください

どうもありがとうヴィンセントよろしく

編集:次のようにすべてのコードを1つのファイルに入れた場合

#include "physics/CHapidll.h"
#include "physics/CHsystem.h"
#include "irrlicht_interface/CHbodySceneNode.h"
#include "irrlicht_interface/CHbodySceneNodeTools.h"
#include "irrlicht_interface/CHdisplayTools.h"
#include "irrlicht_interface/CHirrWizard.h"

#include <irrlicht.h>



// Use the namespace of Chrono

using namespace chrono;

// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

// Get rid of the command windows that pops up when compiling and running
#ifdef _IRR_WINDOWS_
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

IGUIStaticText* text_enginespeed = 0;

class MyEventReceiver : public IEventReceiver
{
public:

    MyEventReceiver(ChSystem* asystem,
                    IrrlichtDevice *adevice,
                    ChSharedPtr<ChLinkEngine> aengine)
    {
        // store pointer to physical system & other stuff
        // so we can tweak them by user keyboard
        msystem = asystem;
        mdevice = adevice;
        mengine = aengine;
    }

    bool OnEvent(const SEvent& event)
    {

        // check if user moved the sliders with mouse..
        if (event.EventType == EET_GUI_EVENT)
        {
            s32 id = event.GUIEvent.Caller->getID();
            IGUIEnvironment* env = mdevice->getGUIEnvironment();

            switch(event.GUIEvent.EventType)
            {
            case EGET_SCROLL_BAR_CHANGED:
                    if (id == 101) // id of 'engine speed' gui
                    {
                        s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
                        double newspeed = 10*(double)pos/100.0;

                        // set the speed into engine object
                        ChFunction_Const *spe_funct = dynamic_cast <ChFunction_Const*> (mengine->Get_spe_funct());
                        spe_funct->Set_yconst(newspeed);

                        // show speed as formatted text in interface screen
                        char message[50]; sprintf(message,"Engine speed: %g [rad/s]",newspeed);
                        text_enginespeed->setText(core::stringw(message).c_str());
                    }
            break;
            }

        }

        return false;
    }

private:
    ChSystem*       msystem;
    IrrlichtDevice* mdevice;
    ChSharedPtr<ChLinkEngine> mengine;
};



int main(int argc, char* argv[])
{

    return 0;
}

そのようにして、インラインとして定義されていないIrrlicht3Dエンジンの関数を何度も定義することを避けます。残念ながら、プロジェクトが大きくなると(3Dエンジンに依存するすべてのクラスを1つの一意の.cppファイルで定義する必要がある)、このコーディング方法は非常に面倒になる可能性があります。複数を回避できるように、従うべきデザインパターンはありますか。各クラスが個別のファイルで定義された定義済みオブジェクト?

どうもありがとう

一番

ヴィンセント

4

1 に答える 1

2

リンカは、2つの関数が複数回定義されていることに不満を持っています。エラーからおそらく理解できるように、これらの関数は次のとおりです。

irr::scene::RTSCamera::OnEvent(struct irr::SEvent const &)
irr::scene::RTSCamera::OnRegisterSceneNode(void)

ここで発生する可能性が最も高いのは、これら2つの関数がヘッダーファイルで定義されていることですが、次のようになります。

  • それらの定義はクラス定義に直接表示されません(したがって、それらは暗黙的にインラインとして宣言されません)。
  • ヘッダーファイルでのクラス外の定義は、明示的にインラインとしてマークされていません。

その結果、ヘッダーが異なる翻訳単位(つまり、異なる.cppファイル)に複数回含まれている場合、同じ関数の複数の定義がそれらの翻訳単位のオブジェクトコードに存在することになります。

それらをマージすると、リンカはODR(One Definition Rule)に違反していると文句を言います。

于 2013-02-09T13:31:51.940 に答える