2

2つのソースファイルに書き込んだプログラムを分割しようとしていますが、それらをリンクするのに問題があり、エラーメッセージが意味をなさないのです。

関連情報を含むファイルの短縮版を提供します。

//grandiose.cpp:

#include "thingy.h"

int main() {}

//thingy.h:
#include<string>
int add (int x, int y);
char * parse_input_fragment(const string & ,const string & , size_t &, size_t &);

//thingy.cpp:
#include "thingy.h"

int add (int x, int y)
{
    return x+y;
}

char * parse_input_fragment(const string & objective,const string & input, size_t & first_finder, size_t & second_finder) {
    char * string_to_int_buffer = new char[64];
    first_finder = input.find(objective, first_finder);
    first_finder = (input.find('=', first_finder))+1;
    second_finder = input.find(';', first_finder);
    int y = 0;
    for(unsigned int x = first_finder; x < second_finder; x++) {
        if (  (input[x] != ' ') && (input[x] != '\n') ) {
            string_to_int_buffer[y] = input[x];
            y++;
        }
    }
    string_to_int_buffer[y] = '\0';
    first_finder = second_finder;
    return string_to_int_buffer;
}

parse_input_fragment関数は、grandiose.cppに入れると正常にコンパイルされますが、説明されているように分割するとエラーメッセージが表示されます。テスト目的で「add」関数を含めましたが、これは正常にコンパイルされます。

私が受け取るエラーメッセージは、thingy.hのプロトタイプに対するものです:エラーC4430:型指定子がありません-intが想定されています。注:C++はdefault-intをサポートしていません

これは文字ポインタの戻り型として明確にマークされており、grandiose.cppから分割されていない場合でも機能するため、ここでの問題についてはかなり混乱しています。

編集:

OK、using名前空間stdを移動した後。適切な場所に移動し、推奨されているようにヘッダーガードを含めました。これらのエラーメッセージは消えましたが、新しいメッセージが表示され、さらに混乱しています。完全なファイルとエラーメッセージを含めます。

エラーメッセージ:province.obj:エラーLNK2005: "public:__thiscall Province :: Province(void)"(?? 0province @@ QAE @ XZ)はすでにgrandiose.objで定義されています

Province.obj:エラーLNK2005: "public:__thiscall Province :: Province(class std :: basic_string、class std :: allocator>、int * const)"(?? 0province @@ QAE @ V?$ basic_string @ DU?$ char_traits @ D @ std @@ V?$ allocator @ D @ 2 @@ std @@ QAH @ Z)はgrandiose.objですでに定義されています

    // grandiose.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"
    #include <vector>
    #include <ctime>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include "market.h"

    int _tmain(int argc, _TCHAR* argv[])
    {
        market England;
        ifstream reader;
        reader.open ("provinces.txt", ios::in);
        if (reader.is_open()) {  //check if txt file successfully opened
            cout << "\n\nprovinces.txt was successfully opened.\n\n";
        }
        else {
            cout << "\n\nfile was not successfully opened.\n\n";
            return (1);
        }
        string reader_buffer;
        while ( reader.good() ) { // while not end of file
            getline (reader, reader_buffer, '}'); // get one province's worth of data from txt file
            if (!reader_buffer.empty()) {
                parse_provinces (reader_buffer); // send data to be parsed
            }
        }
        add(1,2);
        return 0;
    }


    //market.h

    #include <iostream>
    #include <list>
    #include "province.h"
    using namespace std;

    class market
    {
        public:
        list<province> provinces;
    };

    //province.h

    #ifndef PROVINCE_H
    #define PROVINCE_H
    #include <iostream>
    #include <string>

    using namespace std;

    int add (int x, int y);
    char * parse_input_fragment(const string & ,const string & , size_t &, size_t &);

    class province
    {
    public:
        province::province();
        province::province(string, int[]);
        unsigned int * rural_poor;
        unsigned int * urban_poor;
        unsigned int * max_mine_jobs;
        unsigned int * max_farm_jobs;
        unsigned int * employed_mine;
        unsigned int * employed_farm;
        unsigned int * employed_factory;
        string name;
    };
    province::province () {
        rural_poor = new unsigned int(0);
        urban_poor = new unsigned int(0);
        max_mine_jobs = new unsigned int(0);
        max_farm_jobs = new unsigned int(0);
        employed_mine = new unsigned int(0);
        employed_farm = new unsigned int(0);
        employed_factory = new unsigned int(0);
        name = "";
    }
    province::province (string name, int numbers[]) {
        province::name = name;
        cout << "This province is named " << province::name << endl;
        rural_poor = new unsigned int(numbers[0]);
        cout << "Rural poor = " << *rural_poor << endl;
        urban_poor = new unsigned int(numbers[1]);
        cout << "Urban poor = " << *urban_poor << endl;
        max_mine_jobs = new unsigned int(numbers[2]);
        cout << "Max mine jobs = " << *max_mine_jobs << endl;
        max_farm_jobs = new unsigned int(numbers[3]);
        cout << "Max farm jobs = " << *max_farm_jobs << endl;
    }

    province * parse_provinces(string);

    #endif

    //province.cpp

    #include "stdafx.h"
    #include "province.h"

    int add (int x, int y)
    {
        return x+y;
    }

    char * parse_input_fragment(const string & objective,const string & input, size_t & first_finder, size_t & second_finder) {
        char * string_to_int_buffer = new char[64];
        first_finder = input.find(objective, first_finder);
        first_finder = (input.find('=', first_finder))+1;
        second_finder = input.find(';', first_finder);
        int y = 0;
        for(unsigned int x = first_finder; x < second_finder; x++) {
            if (  (input[x] != ' ') && (input[x] != '\n') ) {
                string_to_int_buffer[y] = input[x];
                y++;
            }
        }
        string_to_int_buffer[y] = '\0';
        first_finder = second_finder;
        return string_to_int_buffer;
    }

    province * parse_provinces(string input) {
        size_t first_finder;
        size_t second_finder;
        char * string_to_int_buffer;
        int population_info[4];


        // find the name
        first_finder = input.find('=');
        string name;
        for(unsigned int x = 0; x < first_finder; x++) {
            if ((input[x] != ' ') && (input[x] != '\n')) {
                name.push_back(input[x]);
            }
        }

        // find the rural poor
        string_to_int_buffer = parse_input_fragment("rural_poor", input, first_finder, second_finder);
        population_info[0] = atoi(string_to_int_buffer);

        // find the urban poor
        string_to_int_buffer = parse_input_fragment("urban_poor", input, first_finder, second_finder);
        population_info[1] = atoi(string_to_int_buffer);

        // find max mine jobs
        string_to_int_buffer = parse_input_fragment("max_mine_jobs", input, first_finder, second_finder);
        population_info[2] = atoi(string_to_int_buffer);

        // find max farm jobs
        string_to_int_buffer = parse_input_fragment("max_farm_jobs", input, first_finder, second_finder);
        population_info[3] = atoi(string_to_int_buffer);

        delete[] string_to_int_buffer;
        string_to_int_buffer = NULL;
        province * current_province = new province(name, population_info);
        return current_province;
    }
4

3 に答える 3

2

を含めても、名前空間を使用して型にアクセス<string>する必要もあります。stdstring

#include<string>
using namespace std;

stringは std 名前空間に存在するため、入力するだけでstringは既知の型に名前が付けられません。

stringまたは、ヘッダー内のすべての出現箇所をwithに置き換えて、.cpp 内std::stringのステートメントを使用することもできます (実際、これは、すべての関数と型usingでグローバル名前空間を汚染することを回避するため、望ましい方法です。std

Jason の回答も良いアドバイスです。ヘッダーをインクルード ガードで保護するため、同じヘッダーを 2 回 (たとえば間接的に) インクルードしても、複数の定義によるコンパイラ エラーは発生しません (C++ には 1 つの定義ルールがあります: すべてのクラス一度だけ定義できます)。これは特定のケースでは問題ではありませんが、後者の問題を回避するために習慣を身に付けるのは良いことです

于 2012-04-28T17:18:17.417 に答える
0

複数のファイルをインクルードし始めるときのスタイルの問題として、ヘッダー ファイルの先頭にプリプロセッサ ガードを配置して、それらが 2 回インクルードされて解析エラーが発生するのを防ぐ必要があります。たとえば、すべてのヘッダーに次を配置する必要があります。

//first thing at the top of the header
#ifndef THINGY_H
#define THINGY_H

//...the actual header code

//the very last line of the header
#endif //THINGY_H

そうすれば、コード モジュールのコンパイル中にヘッダー ファイルが 2 回インクルードされる場合、プリプロセッサには既にヘッダー ガード トークンが定義されているため、ヘッダーの 2 番目のコピーからのコードはインクルードされません。 .

于 2012-04-28T17:15:11.697 に答える
0

実装を cpp ファイルに移動するか、実装されたコンストラクター/メソッドをヘッダーにインライン化して、リンカー エラーを解決します。

于 2012-04-28T17:52:39.133 に答える