web-dev-qa-db-ja.com

クラスオブジェクトを動的に作成する方法

クラスboxがあり、ユーザーがboxesを作成できるとします。どうやってするの?私はclassName objectName(args);でオブジェクトを作成することを理解していますが、ユーザー入力に応じて動的にそれを行う方法は?

15
Nebort

正しい答えは、インスタンスを作成するクラスの数によって異なります。

数が非常に多い場合(アプリケーションは、アプリケーション内の任意のクラスのインスタンスを作成できるはずです)、. Netのリフレクション機能を使用する必要があります。しかし、正直なところ、私はビジネスロジックでリフレクションを使用するのがあまり好きではないので、これを行わないことをお勧めします。

実際には、インスタンスを作成したいクラスの数は限られていると思います。そして、他のすべての答えはこの仮定をします。実際に必要なのはファクトリパターンです。次のコードでは、インスタンスを作成するクラスがすべて同じ基本クラスから派生していると仮定します。たとえば、次のようにAnimalとしましょう。

class Animal {...};
class Dog : public Animal {...}
class Cat : public Animal {...}

次に、動物を作成するインターフェースである抽象ファクトリを作成します。

class IFactory
   {
   public:
      Animal *create() = 0;
   };

次に、さまざまな種類の動物ごとにサブクラスを作成します。例えば。 Dogクラスの場合、これは次のようになります。

class DogFactory : public IFactory
   {
   public:
      Dog *create() {return new Dog();}
   };

猫も同じです。

DogFactory :: createメソッドは、戻り値の型が異なる場合でも、IFactory :: createメソッドを無効にします。これは、共変戻り型と呼ばれるものです。これは、サブクラスのメソッドの戻り値の型が基本クラスの戻り値の型のサブクラスである限り許可されます。

次のように、これらのすべてのファクトリのインスタンスをマップに配置できます。

typedef std::map<char *,IFactory *> AnimalFactories
AnimalFactories animalFactories;
animalFactories["Dog"] = new DogFactory();
animalFactories["Cat"] = new CatFactory();

ユーザー入力後、正しいファクトリーを見つけて、動物のインスタンスを作成するように依頼する必要があります。

AnimalFactories::const_iterator it=animalFactories.find(userinput);
if (it!=animalFactories.end())
   {
   IFactory *factory = *it;
   Animal *animal = factory->create();
   ...
   }

これは、典型的な抽象ファクトリアプローチです。他のアプローチもあります。自分自身にC++を教えるとき、私はそれについて小さなCodeProject記事を書きました。あなたはそれをここで見つけることができます: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx

幸運を。

20
Patrick

次のファクトリメソッドは、ユーザー入力に基づいて動的にBoxインスタンスを作成します。

class BoxFactory
{
  public:
    static Box *newBox(const std::string &description)
    {
      if (description == "pretty big box")
        return new PrettyBigBox;
      if (description == "small box")
        return new SmallBox;
      return 0;
    }
};

もちろん、PrettyBigBoxSmallBoxはどちらもBoxから派生しています。 C++設計パターンウィキブック の作成パターンを見てください。おそらくそれらの1つが問題に当てはまるためです。

5

C++では、自動(スタック)および動的(ヒープ)ストレージを使用してオブジェクトを割り当てることができます。

Type variable_name; // variable_name has "automatic" storage.
                    // it is a local variable and is created on the stack.

Type* pointer_name = NULL; // pointer_name is a "pointer". The pointer, itself,
                           // is a local variable just like variable_name
                           // and is also created on the stack. Currently it
                           // points to NULL.

pointer_name = new DerivedType; // (where DerivedType inherits from Type). Now
                                // pointer_name points to an object with
                                // "dynamic" storage that exists on the heap.

delete pointer_name; // The object pointed-to is deallocated.
pointer_name = NULL; // Resetting to NULL prevents dangling-pointer errors.

ポインターとヒープ割り当てを使用して、次のように動的にオブジェクトを構築できます。

#include <cstdlib>
#include <iostream>
#include <memory>
class Base {
    public:
        virtual ~Base(){}
        virtual void printMe() const = 0;
    protected:
        Base(){}
};
class Alpha : public Base {
     public:
        Alpha() {}
        virtual ~Alpha() {}
        virtual void printMe() const { std::cout << "Alpha" << std::endl; }
};
class Bravo : public Base {
     public:
        Bravo() {}
        virtual ~Bravo() {}
        virtual void printMe() const { std::cout << "Bravo" << std::endl; }
};
int main(int argc, char* argv[]) {
    std::auto_ptr<Base> pointer; // it is generally better to use boost::unique_ptr,
                                 // but I'll use this in case you aren't familiar
                                 // with Boost so you can get up and running.
    std::string which;
    std::cout << "Alpha or bravo?" << std::endl;
    std::cin >> which;
    if (which == "alpha") {
        pointer.reset(new Alpha);
    } else if (which == "bravo") {
        pointer.reset(new Bravo);
    } else {
        std::cerr << "Must specify \"alpha\" or \"bravo\"" << std::endl;
        std::exit(1);
    }
    pointer->printMe();
    return 0;
}

関連: 「ファクトリー」オブジェクト指向設計パターン

簡単な方法は、ベクトルを使用することです。まず、ベクターライブラリを含め、一時オブジェクトをクラスとして作成します。

class temp;

次に、クラス型を使用して名前付きオブジェクトなどのベクトルを作成します。

#include <vector>
.
.
vector <class>objects;

次に、オブジェクトを追加するループを追加できます。たとえば、tempという名前のクラスにinputという名前の関数があり、追加したい場合は次のようにします。

while(1){
        temp.input();
        objects.Push_back(temp);
        }

これで動的クラスができました。オブジェクトにアクセスするには、次のように使用できます。

objects[i];

オブジェクトを削除する場合は、次のように使用します。1.ベクター内のオブジェクトの場所を見つけます。 2.ベクトルの最後のブロックの量をそれで変更し、最後のブロックを削除します。

objects[location of the object you want to remove]=objects[location of your last block];
objects.pop_back();

ベクトルの最後のブロックの場所を知りたい場合は、次のようにします。

int lastblock;
lastblock=(objects.size()-1);

注:配列のようなベクトルを使用できます。

0
Lost Gost