C ++管理具有不同对象类型的容器中的ifstream

时间:2016-06-20 22:22:51

标签: c++ class containers ifstream base

我在容器animalColl中创建了DogCat的几个不同对象。我正在尝试调整如何调整读取的文件流,以便如果容器中的对象是Cat,则使用catfile并且Dog使用dogfile。目前,仅使用传递给参数的animalType。是否可以根据对象类型选择使用哪个文件流?

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
    }
}

2 个答案:

答案 0 :(得分: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

一个示例用法(请注意,您必须使用指向基类的指针来获取多态的重要特性,并且您必须将一个函数声明为虚拟以在派生类中覆盖它)。

编辑:@ArchbishopOfBanterbury指出,编辑下面的main.cpp是为了使用智能指针,因为它使用原始指针并导致内存泄漏。

的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

基本思想是在使用指向基类的指针时使用关键字virtual来覆盖行为。所以在我的例子中,getAnimalFilename被覆盖在Dog和Cat类中以返回正确的字符串,而不是将其传递给load()函数。这对你有帮助吗?继续回复此评论,我会尽力帮助。

答案 1 :(得分:0)

有几种方法可以做到这一点。您可以在名为name的类中添加一个元素,并在此处检查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)比较这些类型,使用相同的结构以上:

int main(int argc, const char * argv[]) {
    Dog d, o;
    if (typeid(d) == typeid(o)) {
        //do something
    }
    else {
        //do something else
    }
}