質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.12%

VC++ エラー:削除された関数を参照しようとしています

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 4,178

robomoco

score 27

main.cpp28行目で,Codewriterオブジェクトcodewriter生成時のコンストラクタに,Parserオブジェクトparserを引数にとったところでエラーが出ました。
原因と解決方法が分かりません。

出力

1>------ ビルド開始: プロジェクト: VM_Inverter, 構成: Debug Win32 ------
1>Main.cpp
1>c:\users\ken\documents\nand2tetris\projects\07\virtualmachine\vm_inverter\main.cpp(28): error C2280: 'Parser::Parser(const Parser &)': 削除された関数を参照しようとしています
1>c:\users\ken\documents\nand2tetris\projects\07\virtualmachine\vm_inverter\parser.h(31): note: コンパイラが 'Parser::Parser' をここに生成しました。
1>c:\users\ken\documents\nand2tetris\projects\07\virtualmachine\vm_inverter\parser.h(31): note: 'Parser::Parser(const Parser &)': function was implicitly deleted because a データ メンバー invokes a deleted or inaccessible function 'std::basic_ifstream<char,std::char_traits<char>>::basic_ifstream(const std::basic_ifstream<char,std::char_traits<char>> &)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\fstream(944): note: 'std::basic_ifstream<char,std::char_traits<char>>::basic_ifstream(const std::basic_ifstream<char,std::char_traits<char>> &)': 関数は明示的に削除されました
1>プロジェクト "VM_Inverter.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

main.cpp

#include <iostream>
#include "Parser.h"
#include "CodeWriter.h"

using namespace std;

int main()
{
    Parser parser;
    parser.advance();
    //cout << parser.commandType() << endl;
    cout << parser.arg1() << endl;

    parser.advance();
    //cout << parser.commandType() << endl;
    cout << parser.arg1() << endl;
    cout << parser.arg2() << endl;

    parser.advance();
    //cout << parser.commandType() << endl;
    cout << parser.arg1() << endl;

    parser.advance();
    //cout << parser.commandType() << endl;
    cout << parser.arg1() << endl;
    cout << parser.arg2() << endl;

    CodeWriter codewriter(parser);
}

Parser.h

#pragma once
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>


enum comType{
    C_ERROR,
    C_ARITHMATIC,
    C_PUSH,
    C_POP,
    C_LABEL,
    C_GOTO,
    C_IF,
    C_FUNCTION,
    C_RETURN,
    C_CALL
};

class Parser {
public:
    std::string infilename;
    Parser();            //読みこみファイルを開く
    void advance();        //次のコマンドを読みこむ
    comType commandType();    //コマンドのタイプを返す
    std::string arg1();            //現コマンドの1番目の引数を返す
    int arg2();                //現コマンドの2番目の引数を返す
    std::ifstream ifs;
    std::string curcmd;        //現在コマンド
};

Parser.cpp

#include "Parser.h"
using namespace std;
//クラスParserの実装
Parser::Parser()
{
    cin >> infilename;
    ifs.open(infilename);
    while(ifs.fail()) {
        cin >> infilename;
        ifs.open(infilename);
    }
}

void Parser::advance()
{
    getline(ifs, curcmd);

    while (curcmd[0] == ' ') {
        curcmd.erase(curcmd.begin()+0);
    }
    while (curcmd[0] == '\0') {
        advance();
    }
}

comType Parser::commandType()
{

    //cout << curcmd << endl;

    string curcmdope = curcmd;
    curcmdope = curcmdope.substr(0, curcmd.find(" "));
    if (curcmdope == "add" || curcmdope == "sub" || curcmdope == "neg" ||
        curcmdope == "eq"  || curcmdope == "qt"  || curcmdope == "lt"  ||
        curcmdope == "and" || curcmdope == "or"  || curcmdope == "not") {

        return C_ARITHMATIC;
    }
    else if (curcmdope == "push") {
        return C_PUSH;
    }
    else if (curcmdope == "pop") {
        return C_POP;
    }
    else {
        return C_ERROR;
    }
}

string Parser::arg1()
{
    string curcmdarg1 = curcmd;

    if (commandType() == C_RETURN) {
        cout << "C_RETURNは呼ぶな" << endl;
        return curcmd;
    }
    else if (commandType() == C_ARITHMATIC) {
        return curcmd;
    }
    else if (commandType() == C_PUSH || commandType() == C_POP) {

        while (curcmdarg1[0] != ' ') {
            curcmdarg1.erase(curcmdarg1.begin() + 0);
        }
        while (curcmdarg1[0] == ' ') {
            curcmdarg1.erase(curcmdarg1.begin() + 0);
        }

        curcmdarg1 = curcmdarg1.substr(0, curcmdarg1.find(" "));

        return curcmdarg1;
    }
    else {
        cout << "そのようなコマンドは存在しない" << endl;
    }
}

int Parser::arg2() 
{
    string curcmdarg2 = curcmd;

    if (commandType() == C_PUSH || commandType() == C_POP || 
        commandType() == C_FUNCTION || commandType() == C_CALL) {

        while (curcmdarg2[0] != ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        while (curcmdarg2[0] == ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        while (curcmdarg2[0] != ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        while (curcmdarg2[0] == ' ') {
            curcmdarg2.erase(curcmdarg2.begin() + 0);
        }
        curcmdarg2 = curcmdarg2.substr(0, curcmdarg2.find(" "));
        //cout << "curcmdarg2 " << curcmdarg2 << endl;
        return stoi(curcmdarg2);
    }
}

CodeWriter.h

#pragma once
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>

class CodeWriter {
public:
    std::string outfilename;
    CodeWriter(Parser parser);        //出力先ファイルを開く
    void setFileName(std::string fileName);
    void writeArithmatic(std::string command);
    void writePushPop(std::string command, std::string segment, int index);
    void close();
    std::ofstream ofs;
};

CodeWriter.cpp

#include "Parser.h"
#include "CodeWriter.h"

CodeWriter::CodeWriter(Parser parser)
{
    outfilename = parser.infilename;
    outfilename.erase(outfilename.find(".") + 1, outfilename.find(".") + 3);
    outfilename += "hack";
    ofs.open(outfilename);
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

こんにちは。

Parser::Parser(const Parser &)はコピー・コンストラクタです。
コピー・コンストラクタは自動生成されることも多いのですが、メンバ変数の中にコピーできない変数があると自動生成されません。
そして、std::ifstream ifs;はコピーできないので、Parserのコピー・コンストラクタも自動生成されません。

そして、CodeWriterのコンストラクタは、Parserのインスタンスを受け取っています。ポインタ渡しや参照渡しはないので、Parserはコピーして渡されます。(int型等の変数をポインタ渡しや参照渡ししなければコピーされるのと同じです。)
その時、コピー・コンストラクタが呼ばれます。
が、コピー・コンストラクタが自動生成されていない(=削除された)ため、「削除されたコピー・コンストラクタを呼び出している」エラーとなります。

CodeWriterのコンストラクタはParserをコピーして受け取る必要はなさそうですので、参照渡しにすることで回避できるだろうと思います。

CodeWriterの中でParserを変更していないので、const参照渡しするのが望ましいです。
CodeWriter::CodeWriter(Parser const& parser);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/08 02:07

    値渡しでしたね。気づきませんでした。
    とても詳しく解説していただきありがとうございます。
    参照渡しにしたら無事動きました<^^>

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る