2016-06-20 6 views
2

コンテナanimalCollの中にDogCatのいくつかの異なるオブジェクトを作成しました。私は、コンテナ内のオブジェクトがCatの場合はcatfileが使用され、Dogはdogfileを使用するように、読み込まれるファイルストリームを調整する方法を試しています。現在、パラメータに渡されたanimalTypeだけが使用されます。オブジェクトタイプに基づいてどのファイルストリームが使用されるかを選択することは可能ですか?異なるオブジェクトタイプのコンテナ内でifstreamを管理するC++

void Animal::load(std::string animalType) 
{ 
    std::string file = animalType + ".csv"; 
    std::ifstream lstream(file); 

    for (Animal *a : animalColl) 
    { 
     a->load(lstream); //uses one stream to read all the different objects in container 
    } 
} 
+0

'dynamic_cast'を使用しますか? – Arunmu

答えて

2

残念ながら、なぜあなたが再帰的にロードを呼び出すのか分からないので、私は正確な答えを与えることはできません。私はあなたが探している答えは多態性を使用するつもりだと思います。

animal.h

#ifndef ANIMAL_H 
#define ANIMAL_H 

#include <iostream> 
#include <string> 

class Animal 
{ 
public: 
    void load() 
    { 
     std::string fileName = this->getAnimalFilename() + ".csv"; 
     std::cout << "fileName = " << fileName << std::endl; 
    } 

protected: 
    virtual std::string getAnimalFilename() { return "Animal"; } 
}; 

#endif //ANIMAL_H 

dog.h

#ifndef DOG_H 
#define DOG_H 

#include <string> 
#include <iostream> 

class Dog : public Animal 
{ 

protected: 
    virtual std::string getAnimalFilename() { return "Dog"; } 
}; 

#endif //DOG_H 

cat.h

#ifndef CAT_H 
#define CAT_H 

#include <iostream> 
#include <string> 

class Cat : public Animal 
{ 

protected: 
    virtual std::string getAnimalFilename() { return "Cat"; } 
}; 

#endif //CAT_H 

と使用例(あなたが使用しなければならないことに注意してください。これは基本的な例です。ポリモーフィズムのオーバーライド機能を取得するための基本クラスへのポインタです。関数を仮想としてオーバーライドする必要があります。 n派生クラス)。

EDIT:以下のmain.cppは、生ポインタを使用し、@ArchbishopOfBanterburyによって指摘されたメモリリークを引き起こしたため、スマートポインタを使用するように編集されました。

main.cppに

#include <iostream> 
#include <vector> 
#include <string> 
#include <memory> 
#include "animal.h" 
#include "dog.h" 
#include "cat.h" 

int main(int argc, char *argv[]) 
{ 
    std::vector<std::unique_ptr<Animal>> animalColl; 
    animalColl.emplace_back(new Dog()); 
    animalColl.emplace_back(new Cat()); 
    animalColl.emplace_back(new Cat()); 
    animalColl.emplace_back(new Dog()); 
    for (auto &a : animalColl) { 
     a->load(); 
    } 

    return 0; 
} 

そして出力:

fileName = Dog.csv 
fileName = Cat.csv 
fileName = Cat.csv 
fileName = Dog.csv 

基本的な考え方は、基本クラスへのポインタを使用しているときに動作を上書きするキーワード仮想を使用することです。したがって、私の例では、getAnimalFilenameはDogおよびCatクラスでオーバーライドされ、load()関数に渡すのではなく正しい文字列を返します。それはどんなことに役立ちますか?先に進んでこのコメントに返信して、私ができる限り多くのことを助けようとします。

+0

'main'にメモリリークがあります。 'std :: vector >' – ArchbishopOfBanterbury

+0

のように、生ポインタではなくスマートポインタを使用してください。元の投稿を更新しました。 –

0

これを行う方法はいくつかあります。あなたは、クラスと呼ばれる名前に要素を追加し、インスタンスのタイプをチェックするために、これをstrcmpの可能性:

struct Animal { 
}; 
struct Dog : Animal { 
    string name = "Dog"; 
}; 
struct Cat : Animal { 
    string name = "Cat"; 
}; 

int main() { 
    Dog d; 
    if("Dog" == d.name) { 
     //do something 
    } 
    else if("Cat" == d.name) { 
     //do something else 
    } 
} 

あなたが別のオブジェクトの種類を知っている、または別のオブジェクトを作成するために喜んでいる場合は、これを行う別の方法は次のようになり例えば、DogやCat型の場合は、上記と同じ構造体を使用して、typeid(obj)を使用してこれらの型を比較す​​ることができます。

関連する問題