1

編集:

はぁ、バカみたい。彼に質問してから数か月後まで、c++ファイルのインクルージョンについて適切に説明されたことはありませんでした。私のセットアップがどれほど欠陥があったかについて正確にコメントすることは控えてください。私はよく知っています。

多くの .h および .cpp ファイルを含む複数ファイル プロジェクトがあります。特に io_util.h は、奇妙な一連のエラーを生成します。関数宣言を含むが実装を含まない .h の場合、完全にコンパイルされますが、関数本体がある .cpp では、すべての関数で次のエラーが発生します。

   Multiple markers at this line
- first defined here
- multiple definition of 
 `<namespace>::<function name>(<args>)'

ファイル「io_util.cpp」は、プロジェクト CollectionBase.h に 1 回だけ含まれます。「io_util.h」は「io_util.cpp」にのみ含まれています

以下に 2 つのファイルを示します。

.h:

/*
 * io_util.h
 */

#ifndef IO_UTIL_H_
#define IO_UTIL_H_

#include <iostream>
#include <sstream>
#include <string>
#include <cmath>

#define IO_DEBUG(a) cout << #a << '=' << a << '\n'

#define CASE_SEP 32
#define NUM_CHAR_SEP 48

namespace std
{
    void getVar(int&, int);
    
    void getVar(double&, double);
    
    void getVar(unsigned&, unsigned);
    
    int get_num_digits(int);
    
    int get_digit(int, const int, const int);
    
    string value_of(int);
}

#endif /* IO_UTIL_H_ */

.cpp:

/*
 * io_util.cpp
 */
#ifndef IO_H_
#define IO_H_

#include "io_util.h"

namespace std
{

void getVar(int& i, int forbidden = NAN)
{
    string str;

    while(true)
    {
        getline(cin,str);

        if(str.find_first_not_of("-0123456789") != string::npos || !(stringstream(str) >> i))
        {
            cout << "invalid input.\n\n";
        }
        else if(i == forbidden)
        {
            cout << "illegal value.\n\n";
        }
        else
        {
            break;
        }
    }
}

void getVar(double& d, double forbidden = NAN)
{
    string str;

    while(true)
    {
        getline(cin,str);

        if(str.find_first_not_of("-.0123456789eE") != string::npos || !(stringstream(str) >> d))
        {
            cout << "invalid input.\n\n";
        }
        else if(d == forbidden)
        {
            cout << "illegal value.\n\n";
        }
        else
        {
            break;
        }
    }
}

void getVar(unsigned & u, unsigned forbidden = NAN)
{
    string str;

    while(true)
    {
        getline(cin,str);

        if(str.find_first_not_of("0123456789") != string::npos || !(stringstream(str) >> u))
        {
            cout << "invalid input.\n\n";
        }
        else if(u == forbidden)
        {
            cout << "illegal value.\n\n";
        }
        else
        {
            break;
        }
    }
}

int get_num_digits(int i)
{
    if(i < 0)
    {
        i = -i;
    }

    int result = 1;

    while(i > 10)
    {
        i /= 10;
        result++;
    }

    return result;
}

int get_digit(int i, const int num_digits, const int dig)
{
    if(num_digits < dig)
    {
        return 0;
    }

    const int dig_p10 = pow(10.0,num_digits - dig);

    i -= dig_p10 * round(i/dig_p10);

    if (dig < num_digits - 1)
    {
        i = round(i/int(pow(10.0,num_digits - dig - 1)));
    }

    return i;
}

string value_of(int i)
{
    string str;

    if (i < 0)
    {
        str += "-";
        i = -i;
    }

    const int num_dig = get_num_digits(i);

    for(int n = 0; n < num_dig; n++)
    {
        str += char(get_digit(i, num_dig, n) + NUM_CHAR_SEP);
    }

    return str;
}

}

#endif /*IO_H_*/

このサイトで同様の現象に関する多くの質問を調べましたが、どれも役に立ちませんでした.

4

1 に答える 1

1

まず、コンパイルするコード ファイルのソースファイル リストにio_util.cpp が含まれている必要があります。そこに含まれる機能を必要とするプロジェクトのどこにでも、CollectionBase.h を含む io_util.h を含める必要があります。.cpp ファイルを #includeしないでください(つまり、#include " io_util.cpp " は許可されません)。

次に、io_util.h ヘッダーは getVar() と呼ばれる std 名前空間 (これもダメ) 内で関数を宣言します。後続パラメータのデフォルト パラメータ値はそこに属します。io_util.cpp ファイルにはありません。

これらの両方を修正すると、大幅に先に進むことができます。

于 2012-11-06T03:29:06.520 に答える