在类中实现函数会导致错误:成员引用基类型' ifstream(字符串)'不是结构或联盟

时间:2014-09-29 16:56:20

标签: c++ ifstream

我正在尝试实现一个从文本文件中读取数据列并将其存储在矢量中的函数,该函数可以正常工作。但是,当我尝试在一个类中实现它时,我显然错过了一些步骤。这会导致终端输出以下消息:

的外出
error: member reference base type
      'ifstream (string)' is not a structure or union
                ...

error: member reference base type
      'ifstream (string)' is not a structure or union
                while(!file.eof()){
                ..
error: invalid operands to binary
      expression ('ifstream (*)(string)' and 'double')
                        file >> line;

在我的课程中,我尝试实现以下函数与其数据成员一起使用:

#include <iostream>
#include <vector>
#include <stdio.h>
#include <fstream> 

using namespace std;

class spectData{
public:
    vector<double> x, y, z;
    vector< int> A;
    vector<double> readVector(string){
        ifstream file(string);
        double line;
        vector<double> a;

        if(file.fail()){
            cout << "-----------------\n";
            cout << "Input file error!\n";
        }
        while(!file.eof()){
            file >> line;
            a.push_back(line);
        }
        return a;
    };
};

关于为什么这在函数内部不起作用,但是在main函数内部的任何提示?

4 个答案:

答案 0 :(得分:6)

using namespace std;  
...
vector<double> readVector(string){
//                        ~~~~~~^
//                        missing parameter name
    ifstream file(string);
//                ~~~~~^
//                whoops, type name aka std::string instead of parameter name

您的ifstream file(string);当前所执行的操作,它声明了一个函数file,它按值std::string类型的参数获取并返回std::ifstream实例。因此你得到的错误。您可能要做的是为file的构造函数提供路径参数:

vector<double> readVector(const string& path){
//                        ~~~~~~~~~~~~~~~~~^
//                        parameter name
    ifstream file(path.c_str());
//                ~~~^ ~~~~~~^
//                 

答案 1 :(得分:5)

此代码中的问题很多,包括:

  • 未能加入<string>。不要依赖另一个标题为你做这件事。
  • 无效的参数命名(如同,没有;请记住参数为Type name)。
  • 基于上面的错误,ifstream file(string);因此声明一个名为file函数,它接受string参数并返回ifstream(这是不可能的,因为该类不支持复制构造,但支持移动构造,而不是在这里重要。)
  • 使用.eof()作为循环条件,几乎总是错误(这也不例外)。 Read this for why.
  • Minor:重新进行迭代读取操作。 std::istream_iterator为您提供此功能,应该被利用。
  • 次要:使用using namespace std;
  • 覆盖此内容

例如:

#include <iostream>
#include <fstream> 
#include <string>
#include <vector>
#include <iterator>

class spectate
{
public:
    std::vector<double> x, y, z;
    std::vector< int> A;

    std::vector<double> readVector(const std::string& fname)
    {
        std::vector<double> res;

        std::ifstream file(fname);
        if(!file)
        {
            std::cout << "-----------------\n";
            std::cout << "Input file error!\n";
        }
        else
        {   // dump the file of doubles into your vector
            std::copy(std::istream_iterator<double>(file),
                      std::istream_iterator<double>(),
                      std::back_inserter(res));
        }
        return res;
    }
};

说实话,如果错误报告由调用者处理(例如空文件,向量等),你可以放弃大部分内容,此时整个成员可以简化为:

std::vector<double> readVector(const std::string& fname)
{
    std::ifstream file(fname);
    return std::vector<double> {
        std::istream_iterator<double>(file),
        std::istream_iterator<double>() };
}

这有点让人怀疑这个功能是否真正需要。呼叫者可以很容易地完全做到这一点。

答案 2 :(得分:2)

string是您通过using namespace std无意中提取的类型名称。因此,file不是您的意图 - 它是一个功能std::string并返回std::ifstream。避免using namespace std除非在非常受控制的范围内 - 绝对不在头文件中。

答案 3 :(得分:1)

#include <vector> 确实包括std::stringusing namespace std; std::string变为类型string后,您无法使用string作为变量名称,因为它是一种类型。

您应该写using std::vector;而不是using namespace std;