7

次の階層があります。

class base
{
public:
   virtual ~base(){}
   virtual void foo() {}
};

template <typename T>
class derived1 : public base
{
   virtual void foo() {};
};

template <typename T>
class derived2 : public base
{
   virtual void foo() {};
};

base へのポインターが与えられたので、基になるものが派生 1 か派生 2 かを調べたいと思います。問題は、派生1と派生2の両方が多くの異なる型に特化できることです.dynamic_castを使用してダウンキャストをテストするには、テンプレートの型を知る必要があります. 私は厄介で、保守不可能で、不完全なコードのビットになってしまいました:

base* b = new derived1<int>();

if (dynamic_cast<derived1<int>*> ||
    dynamic_cast<derived1<unsigned int>*> ||
    dynamic_cast<derived1<double>*>)
  std::cout << "is derived1";
else if (dynamic_cast<derived2<int>*> ||
    dynamic_cast<derived2<unsigned int>*> ||
    dynamic_cast<derived2<double>*>)
  std::cout << "is derived2";

型の特殊化を処理できるより良い方法はありますか?

4

4 に答える 4

9

型に依存するロジックを型に移動します。

それ以外の:

if (dynamic_cast<derived1<int>*>(b) ||
    dynamic_cast<derived1<unsigned int>*>(b) ||
    dynamic_cast<derived1<double>*>(b))
  std::cout << "is derived1";
else if (dynamic_cast<derived2<int>*>(b) ||
    dynamic_cast<derived2<unsigned int>*>(b) ||
    dynamic_cast<derived2<double>*>(b))
  std::cout << "is derived2";

virtual print_name() constに関数を追加してからbase、次のようにします。

void example() {
    std::unique_ptr<base> b(new derived1<int>());
    b->print_name();
}
class base
{
public:
   ~base(){}
   virtual void foo() {}
   virtual void print_name() const = 0;
};

template <typename T>
class derived1 : public base
{
   virtual void foo() {}
   virtual void print_name() const {
       std::cout << "is derived1";
   }
};

template <typename T>
class derived2 : public base
{
   virtual void foo() {}
   virtual void print_name() const {
       std::cout << "is derived2";
   }
};
于 2012-03-05T02:42:33.153 に答える
7

basederived1またはの間にテンプレート化されていないクラスを挿入しderived2ます。

class base
{
public:
   virtual ~base() {}  // **NOTE** Should be virtual
   virtual void foo() {}
};

class derived1_base : public base
{
};

template <typename T>
class derived1 : public derived1_base
{
public:
   virtual void foo() {}
};

class derived2_base : public base
{
};

template <typename T>
class derived2 : public derived2_base
{
public:
   virtual void foo() {}
};

コメントで、あなたは次のように述べました:

[したい] それぞれに対して特定の関数を呼び出します-ところで、派生1と派生2以上のものがあります

その (仮想) 関数を に追加すると、もうderived1_base知る必要さえありTません。

if (dynamic_cast<derived1_base*>(foo))
{
  std::cout << "is derived1";
  dynamic_cast<derived1_base*>(foo)->specific_derived1_function();
}
else if (dynamic_cast<derived2_base*>(foo))
{
  std::cout << "is derived2";
  dynamic_cast<derived2_base*>(foo)->specific_derived2_function();
}

注:コードの匂いdynamic_cast<>のリストを検討しており、アプローチを再考することを強くお勧めします。

于 2012-03-05T02:43:21.203 に答える
3

ある種のメタタイプ チェックを行う仮想メソッドを追加できます。

class base
{
public:
    ~base(){}
    virtual void foo() {}
    virtual bool isa(const char* type_to_test){
          return strcmp(type_to_test,"base")==0;}
};

template <typename T>
class derived1 : public base
{
   virtual void foo() {};
   virtual bool isa(const char* type_to_test){
   return strcmp(type_to_test,"derived1")==0;}
};
于 2012-03-05T02:44:02.623 に答える
2

解決策 1: 仮想機能をもう 1 つ追加します。

enum DerivedType
{
    One,
    Two,
    ...
};

class base 
{ 
public: 
   ~base(){} 
   virtual void foo() {}
   virtual DerivedType GetType() = 0;
}; 

template <typename T> 
class derived1 : public base 
{ 
   virtual void foo() {};
   virtual DerivedType GetType() { return One; }
}; 

template <typename T> 
class derived2 : public base 
{ 
   virtual void foo() {};
    virtual DerivedType GetType() { return Two; }
}; 

解決策 2: タグ クラスを使用する:

class Base
{
public:
    virtual ~Base() { }
};

class Derived1Tag
{ };

class Derived2Tag
{ };

template <class T>
class Derived1 : public Base, public Derived1Tag
{ };

template <class T>
class Derived2 : public Base, public Derived2Tag
{ };


int main(int argc, char** argv)
{
    Derived1<int> d1;
    Derived2<int> d2;

    cout << dynamic_cast<Derived1Tag*>((Base*)&d1) << endl;
    cout << dynamic_cast<Derived1Tag*>((Base*)&d2) << endl;

    return 0;
}
于 2012-03-05T02:43:35.147 に答える