2016-09-02 7 views
-1

さまざまなソースからの助けを借りて、ファクトリが派生クラスに依存しない単純なテンプレートベースのファクトリパターンクラスを作成することができました。ここにコードをアップロードしました:https://github.com/piyushsoni/FactoryPattern。それは完璧ではないかもしれませんが、この例では私の驚きにもかかわらず動作します。これを私たちの大きな実際のコードベースでほぼ同じように使用すると、のいくつかのほんの少しののための 'DerivedFactory'のコンストラクタが呼び出され、他のものについては完全に無視されます。 DerivedFactoryオブジェクトにアクセスできる静的関数を定義してから実際にを呼び出すと、派生したファクトリオブジェクトを左辺値に割り当てることができます(必要なし)。私はmain.cppでそれらを作成してください)。コンパイラがここで不必要な最適化を行っているようです。スタティックオブジェクトのコンストラクタがこのファクトリコード(C++)で呼び出されないのはなぜですか?

このサンプルプロジェクトはVC 15でテストされていますが、実際のコードベースではC++ 11機能を有効にしたインテル®コンパイラーを使用しています(WindowsではMSVC11、Linuxではgccを使用)。 MSVC11とGCC 4.8以降で、これらの単純な静的オブジェクトが毎回作成されるように、どうすれば修正できますか?

編集:私はきれいな質問を保つために、ここですべてのコードを書くと、1つの公共の場所でソースコードを置くことが、フィードバックに今ここにそれをやって(そしてそれが閉じ避けるために)避けたかったです。この単純なコードが実際に動作していると書いておきたいが、Windows上でMSVC11を内部的に使用しているインテルコンパイラを使用してコンパイルされた商用コードに入れると、ほとんど同じコードが動作しない。他の質問がある場合は、コメントでそれらを尋ねてください。私は答えようとします。答えを出す前に、質問を閉じないようにしてください。私は上に直面している正確な問題を書いています。ここで

は、ファイルは次のとおりです。

ShapeFactory.h

#pragma once 

#include <map> 
using namespace std; 

#include "Shape.h" 

#define REGISTER_CLASS(objectClass) static DerivedFactory<objectClass> shape##objectClass(Type_ ## objectClass); 

class Shape; 
class ShapeFactory; 
typedef map<ShapeType, ShapeFactory*> mapTypeShapeFactoryByType; 

class ShapeFactory 
{ 
private: 
    mapTypeShapeFactoryByType mapShapeTypeByFactory; 
protected: 
    ShapeFactory() {} 
    virtual Shape* Create() { return NULL; } 
private: 
    ShapeFactory(const ShapeFactory&); 
public: 
    virtual ~ShapeFactory() {} 
    static ShapeFactory& GetShapeFactory(); 

    Shape* CreateShape(ShapeType type); 

    virtual void DestroyShape(Shape* object) { delete object; object = nullptr; } 
    void RegisterFactory(ShapeType type, ShapeFactory* factory); 
}; 

template<typename ShapeClass> 
class DerivedFactory : public ShapeFactory 
{ 
public: 
    DerivedFactory(ShapeType type) 
    { 
     ShapeFactory::GetShapeFactory().RegisterFactory(type, this); 
    } 
    ~DerivedFactory() {} 
    Shape* Create() { return new ShapeClass(); } 
}; 

ShapeFactory.cpp

#include "ShapeFactory.h" 

//mapTypeShapeFactoryByType ShapeFactory::mapShapeTypeByFactory; 
//ShapeFactory* ShapeFactory::mInstance = NULL; 

ShapeFactory& ShapeFactory::GetShapeFactory() 
{ 
    static ShapeFactory instance; 
    return instance; 
} 

Shape * ShapeFactory::CreateShape(ShapeType type) 
{ 
    if (mapShapeTypeByFactory.find(type) != mapShapeTypeByFactory.end()) 
     return mapShapeTypeByFactory[type]->Create(); 
    else 
     return nullptr; 
} 

void ShapeFactory::RegisterFactory(ShapeType type, ShapeFactory * factory) 
{ 
    mapShapeTypeByFactory[type] = factory; 
} 

Shape.h

#pragma once 

#include <string> 
using namespace std; 

enum ShapeType 
{ 
    Type_Unknown, 
    Type_Circle, 
    Type_Rectangle, 
    Type_Polygon 
}; 

class Shape 
{ 
    std::string name; 
public: 
    virtual ~Shape() {} 
    virtual ShapeType GetType() { return Type_Unknown; } 
}; 

Rectangle.h

#pragma once 
#include "Shape.h" 
#include <iostream> 

using namespace std; 

class Rectangle : public Shape 
{ 
public: 
    Rectangle(); 
    virtual ~Rectangle(); 
    virtual ShapeType GetType() { return Type_Rectangle; } 
private: 
    float points[4][3]; 
}; 

Rectangle.cpp

#include "Rectangle.h" 
#include "ShapeFactory.h" 

static DerivedFactory<Rectangle> RectangleFactory(Type_Rectangle); 

Rectangle::Rectangle() 
{ 
    cout << "The factory created new Rectangle! \n"; 
} 

Rectangle::~Rectangle() 
{ 
    cout << "The Rectangle object was destroyed \n"; 
} 

Circle.h

#pragma once 
#include "Shape.h" 
#include <iostream> 

using namespace std; 

class Circle : public Shape 
{ 
public: 
    Circle(); 
    virtual ~Circle(); 
    virtual ShapeType GetType() { return Type_Circle; } 

private: 
    float center[3]; 
    float radius; 
}; 

Circle.cpp

#include "Circle.h" 
#include "ShapeFactory.h" 

static DerivedFactory<Circle> CircleFactory(Type_Circle); 

Circle::Circle() 
{ 
    cout << "The factory created new Circle! \n"; 
} 

Circle::~Circle() 
{ 
    cout << "The Circle object was destroyed \n"; 
} 

main.cppに

#include <iostream> 
#include <string> 
#include <map> 
#include "ShapeFactory.h" 
#include "Shape.h" 
#include "Circle.h" 
#include "Rectangle.h" 

using namespace std; 

int main() 
{ 
    ShapeFactory& factory = ShapeFactory::GetShapeFactory(); 

    Circle* vec = (Circle*)factory.CreateShape(Type_Circle); 
    cout << "Object type is : " << vec->GetType() <<"\n"; 
    factory.DestroyShape(vec); 

    Rectangle* con = (Rectangle*)factory.CreateShape(Type_Rectangle); 
    cout << "Object type is : " << con->GetType() << "\n"; 
    factory.DestroyShape(con); 



    getchar(); 
    return 0; 
} 

感謝!!

+0

読者がこれを試すことができるように、質問自体には最小限の完全な例を記入してください。現時点で**関連する例がない**として閉じるために投票してください。 –

+0

@ Cheersandhth.-Alf:複数のファイルがあるのでここで質問をするためにgithubにプロジェクトをアップロードしましたが、ここでそれらをすべて追加するように編集します。しかし、著者が質問を編集できるようにするために数時間も待つことなく、質問をすばやく「閉じる」という熱意を理解していません。何度も何度もリクエストされた編集が行われていますが、誰かが閉鎖された質問に訪れました。それは初心者を助ける方法ではありません。 –

答えて

0

コンパイル後、リンカーはオブジェクトファイル内のすべてのシンボルを解決します。コンパイルされたコードで呼び出されるときのような必要性がない限り、コンパイラが最終的にその定義にリンクまたは解決されるシンボルを生成するためには、静的またはそれ以外の関数宣言だけでは不十分です。

この関連する質問Static variables initialisation orderもまたいくつかの洞察を提供します。

コードを確認して、派生クラスを解決する必要があるかどうかを確認することができます。

@alfが推奨するように、ご質問に最小限のコードスニペットを含めることで、ここでの回答に集中できます。

+0

ありがとう、ここでコードをここに含めるために、ここで問題を編集しました。私は質問が関連しているかどうかわからない、私の静的オブジェクトはちょうど初期化されていない、私は自動的に起こる限り、彼らの順序について心配していない。 –

+0

drivedクラスのコンストラクタへの呼び出しをトリガするコードはどれですか?ところで、それはたくさんのコードです。 5行以下の簡単なクラスで問題を説明することができれば、それは私の反応に集中するのに役立ちます。 – sith

+0

私は、Rectangle.cppとCircle.cppで作成された派生Factoryクラスコンストラクタの呼び出しを期待しています。これは、静的オブジェクトを宣言する最上部にあります。はい、それはたくさんのコードですが、問題に直面している正確なサンプルをアップロードしたかったのです。サンプルの目的のリストから派生したクラスの1つを削除することができました。ありがとう! –

関連する問題