【问题标题】:C++ managing ifstream in a container with different object typesC++ 在具有不同对象类型的容器中管理 ifstream
【发布时间】:2016-06-20 22:22:50
【问题描述】:

我在容器 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
    }
}

【问题讨论】:

  • 使用dynamic_cast ?

标签: c++ class containers ifstream base


【解决方案1】:

不幸的是,我不确定您为什么要递归调用 load,所以我无法给出确切的答案。我认为您正在寻找的答案将是使用多态性。这是一个基本示例:

动物.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

狗.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

猫.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 来覆盖行为。因此,在我的示例中,在 Dog 和 Cat 类中覆盖 getAnimalFilename 以返回正确的字符串,而不是将其传递给 load() 函数。这有帮助吗?继续回复此评论,我会尽力提供帮助。

【讨论】:

  • main 中存在内存泄漏。在这种情况下,使用智能指针,而不是原始指针 - 即 std::vector&lt;std::unique_ptr&lt;Animal&gt;&gt;
  • 谢谢,很好。我已经更新了原帖。
【解决方案2】:

有几种方法可以做到这一点。您可以将一个元素添加到名为 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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 2013-07-22
    • 2013-08-14
    • 2021-11-21
    • 1970-01-01
    相关资源
    最近更新 更多