6

たとえば、ポインタを常にmap<int,void*>holdどこから保存するかを提案します。後でstatic_castを介してポインタをキャストバックしても安全ですか。void*classA

classA* ptr = static_cast<classA*>( holditerator->second );

void*使用される理由はhold、が何であるかを知らないいくつかのcppファイルによって使用されるヘッダーで定義されたクラスのメンバーであるためclassAです。これらのcppファイルに定義のヘッダーを含める必要がありclassAますが、これは多くの理由で実行できません。

4

3 に答える 3

13

はい、static_castその場合は問題ありません。正しい使用方法です。

classA*そもそもなぜポインタを保存しないのかと聞かなければなりません。派生クラスポインタをそこに配置する場合は、注意してください。派生クラスポインタをマップに配置するclassA* 前に、派生クラスポインタを(暗黙的または明示的に)アップキャスト/アップコンバートする必要があります。

ただし、派生クラスポインターもマップに配置した場合でも、派生クラスポインターは暗黙的に基本クラスポインターに変換できるため、基本クラスポインターで十分です。

void *が使用される理由は、holdが、classAが何であるかを知らない一部のcppファイルによって使用されるヘッダーで定義されたクラスのメンバーであるためです。

これは、レイヤリング違反を防ぐ正当な理由になる可能性があります。

これらのcppファイルにclassA定義のヘッダーを含める必要がありますが、これは多くの理由で実行できません。

あなたの場合、それはおそらく必要ではありません。前方宣言で十分です。ヘッダーがマップに何が配置されるかを知っているが、追加のヘッダーを含めないようにしたい場合は、これが最適な方法です。

于 2012-08-25T09:53:56.197 に答える
6

ヨハネスが説明したように、それstatic_castは大丈夫です。ClassAcppファイルへの依存関係を防ぐ別の手法は、 pimplイディオムを使用することです。

// in header file
class classB {
public:
    classB();
    ~classB();
private:
    class impl;
    unique_ptr<impl> pimpl;
};



// in implementation file
#include "classA.hpp"

class classB::impl 
{
    std::map<int, classA> hold;  // hidden in implementation file
};

classB::classB() : pimpl{ new impl{ /*...*/ } } { }
classB::~classB() { } 
于 2012-08-25T10:10:19.340 に答える
2

マップのユーザーが実際の型について知らないはずであるという理由だけでヘッダーにvoid*を書き込むことは、ClassAについて知っている場所を含め、コード内のあらゆる場所で型の安全性が失われるため、お勧めできません

検討

  1. コードのすべての部分が知っている可能性のあるクラスからClassAを導出します。
  2. マップをオブジェクトにラップします。このオブジェクトは、クラスAではなく、マップを処理する必要があるコードの部分へのインターフェイスを提供します。
  3. ヘッダーファイルでクラスClassAを宣言しますが、定義しません(ClassAが宣言されているが、定義されていない場所でオブジェクトが破棄されると危険な場合があります)、
  4. テンプレートを使用して、
  5. マップを含むクラスを派生サブクラスとして実装し、マップフィールドを派生サブクラスに配置できるようにします。

ポイント5:イラスト(=テンプレートパターン)

それ以外の

class Containing {
    private:
       map<int,void*> myMap;
    public:
       void somePublicFunction () { // ...implementation }
};

あなたが書く

// Containing.h
class Containing {
   protected:
       virtual void doSomething () = 0;
   public:
       static Containing* Create ();
       void somePublicFunction () { doSomething (); }
       virtual ~Containing () { }
};

// Containing.cc
#include ContainingImplementation.h
Containing* Containing::Create () { return new ContainingImplementation; }

// ContainingImplementation.h / cc
class ContainingImplementation : public Containing {
   protected:
      virtual void doSomething () { // ... }
   private:
      map<int,ClassA*> myMap;
   public:
      virtual ~ContainingImplementation () { }
};
于 2012-08-25T10:05:04.267 に答える