【问题标题】:Error where no default constructor exists for a class类不存在默认构造函数的错误
【发布时间】:2016-02-10 05:46:40
【问题描述】:

我正在开发一个程序,它应该解析命令行输入,读取输入文本文件,然后执行测试文件中指定的步骤序列。

在处理标记器类一段时间后,我遇到了一个错误,即一个错误,我不确定如何解决。

所以,我有 Tokenizer.h:

#ifndef _TOKENIZER_GUARD
#define _TOKENIZER_GUARD 1
#include <string>
#include <cstdlib>
#include <climits>
#include <cfloat>
#include <iostream>
#include <fstream>

#include "Token.h"

//
// A class to create a sequence of tokens from an input file stream.
//
class Tokenizer
{
    public:
        Tokenizer(const std::string&, std::ostream&);
        Tokenizer(Tokenizer&); // Copy Constructor -I
        virtual ~Tokenizer();

        virtual int nextInt();
        virtual bool hasNextInt() const;
        virtual long nextLongInt();
        virtual bool hasNextLongInt() const;
        virtual float nextFloat();
        virtual bool hasNextFloat() const;
        virtual std::string next();
        virtual bool hasNext() const;
        Tokenizer& operator= (Tokenizer&); // overloaded equals operator

    protected:

    private:
        Tokenizer();
        std::ifstream stream;
        std::ostream _os;
        Token _token;
};

#endif

还有 Tokenizer.cpp:

#include <string>
#include <cstdlib>
#include <climits>
#include <cfloat>
#include <iostream>
#include <fstream>

#include "Tokenizer.h"

Tokenizer::Tokenizer()
{    //error occurs here

}
// Constructor 
Tokenizer::Tokenizer(const std::string& s, std::ostream& o)
{   //error occurs here
    stream.open(s);
    std::string t;
    getline(stream, t, ' ');
    _token = Token(t);
}


// Copy Constructor 
Tokenizer::Tokenizer(Tokenizer& t) :_token(t._token), stream(t.stream), _os(t._os)
{

}


// Destructor
Tokenizer::~Tokenizer()
{
     stream.close();
}

// Saves current int to return, then moves _token to the next value 
int Tokenizer::nextInt()
{
    int temp = _token.toInteger();
    std::string t;
    getline(stream, t, ' ');
    _token = Token(t);
    return temp;
}

// Checks to see if there is a next value and if it is an int
bool Tokenizer::hasNextInt() const
{
    return _token.isInteger() && hasNext();
}

// same as nextInt but long -I
long Tokenizer::nextLongInt()
{
    long temp = _token.toLongInteger();
    std::string t;
    getline(stream, t, ' ');
    _token = Token(t);
    return temp;
}

// same as hasNextInt but Long 
bool Tokenizer::hasNextLongInt() const
{
    return _token.isLongInteger() && hasNext();
}

// same as nextInt but Float 
float Tokenizer::nextFloat()
{
    float temp = _token.toFloat();
    std::string t;
    getline(stream, t, ' ');
    _token = Token(t);
    return temp;
}

// same as hasNextInt but float 
bool Tokenizer::hasNextFloat() const
{
    return _token.isFloat() && hasNext();
}

//Returns the next token 
std::string Tokenizer::next()
{
    std::string temp = _token.get();
    std::string t;
    getline(stream, t, ' ');
    _token = Token(t);
    return temp;
}

//True when it is not the end of the file
bool Tokenizer::hasNext() const
{
    return stream.eofbit != 1;
}

//Overloaded = operator 
Tokenizer& Tokenizer::operator= (Tokenizer& t)
{
    _token = t._token;
    stream = t.stream;
    _os = t._os; //error occurs here
}

我得到了错误

'std::basic_ostream>': 没有合适的默认>构造函数可用

对于构造函数。后来,当我使用 'stream = t.stream' 和 '_os = t._os' 时,我得到了错误

函数“std::basic_ostream<_elem _traits>::operator=(const >std::basic_ostream<_elem _traits>::_Myt &) [with _Elem=char, >_Traits=std::char_traits]” (在 >"x:\Visual\VC\include\ostream" 的第 85 行声明)不能被引用——它是一个已删除的 >function

我一直在尝试为第一个错误找到某种解决方案,但我不明白是什么原因造成的。有人建议我创建一个复制构造函数,但它似乎并没有解决这个问题。我还在下面包含了 Token.h。

#ifndef _TOKEN_GUARD
#define _TOKEN_GUARD 1

#include <string>
#include <cstdlib>
#include <climits>
#include <cfloat>

//
// Token class
//
class Token
{
public:
    Token(const std::string& t) : _token(t) { }

    virtual std::string get() const { return _token; }

    virtual long toLongInteger() const;
    virtual bool isLongInteger() const;
    virtual int toInteger() const;  // for int and is int functions
    virtual bool isInteger() const; //
    virtual float toFloat() const;
    virtual bool isFloat() const;
    virtual bool isNonNumeric() const;
    Token() : _token("") {}
    std::string _token;
protected:

};

#endif

如果我说得太含糊或类似的话,我提前道歉。我很乐意提供其他需要的东西(因为我现在被困住了)。

【问题讨论】:

    标签: c++ c++11 tokenize


    【解决方案1】:

    编译器错误信息非常清楚。使用时:

    Tokenizer::Tokenizer(const std::string& s, std::ostream& o)
    {   //error occurs here
        stream.open(s);
        std::string t;
        getline(stream, t, ' ');
        _token = Token(t);
    }
    

    成员变量os_ 是默认构造的。由于std::ostream中没有默认构造函数,所以os_无法初始化。

    我猜你的意思是用Tokenizer的构造函数的输入参数来初始化成员变量os_,比如:

    Tokenizer::Tokenizer(const std::string& s, std::ostream& o) : os_(o) 
    {
       ...
    

    即使这样也行不通,因为std::ostream 没有复制构造函数。您需要将成员变量更改为引用对象。

    std::ostream& os_;
    

    那么,你就可以放心使用了:

    Tokenizer::Tokenizer(const std::string& s, std::ostream& o) : os_(o) 
    {
       ...
    

    您只需要确保输入参数oTokenizer 被销毁之前没有被销毁。否则,Tokenizer 对象将留下一个悬空引用。

    【讨论】:

    • 在 Tokenizer 之前销毁输入参数仍然有点麻烦(感谢您清理构造函数),这仍然导致很多尝试引用已删除的函数.例如,当复制构造函数尝试引用它时,我得到: >function "std::basic_ifstream<_elem _traits>::basic_ifstream(const std::basic_ifstream<_elem _traits>::_Myt &) [with _Elem= char, _Traits=std::char_traits]"(在 "x:\Visual\VC\include\fstream" 的第 825 行声明)不能被引用——它是一个已删除的函数
    • basic_ifstream 已删除复制构造函数 (basic_ifstream constructor),因此您无法按预期复制它。您应该使用不同的方法,例如保留流指针或在复制构造函数中创建全新的流对象。
    猜你喜欢
    • 1970-01-01
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多