0

各クラスが他のクラスに関連する 3 つのクラスがあり、そのうちの 3 つは同じ関数を使用するため、すべての人が使用する「外部」関数を配置する functions.h ファイルを作成することにしました。
デモンストレーションのために:

functions.h
 len function
 subs function
A.cpp
  #include "functions.h"
  #include "A.h"
  #include "B.h"
  cout<<len(word);
B.cpp
   #include "functions.h"
   #include "B.h"
   #include "A.h"
   cout<<subs(word,0,1);
C.cpp
   cout<<len(word);

それらにはすべて、ヘッダーガードを使用しているヘッダーファイル用に、特定の関数を含む functions.h ファイルが含まれています。
プロジェクトをビルドすると、次のエラーが表示されます。

Error   1   error LNK2005: "int __cdecl len(char *)" (?len@@YAHPAD@Z) already defined in A.obj  C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\1033\Ass3\Ass3\B.obj Ass3

同じエラーが subs(function) にあります。
なぜそれが起こるのですか?
ありがとう!


編集:
functions.h

#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <math.h>

  int len(char *w){
     int count=0;
    int i=0;
  while (w[i]!='\0')
      {
          count++;
          i++;
      }
 //cout<<"Length of word is:"<<count<<"\n";
  return count;

}
  char *subs(char *w,int s,int e){
    int i,j=0;
    int size=0;

     size=abs((e))+1;
     //cout<<"new size is:"<<size<<"\n";
     char *newW=new char[size];


     for(i = 0 ;i<e; i++)
        {

           newW[i]=w[s];
           s++;

        }

    newW[i]='\0';
    return newW;

   }

   #endif

Word.cpp

#include "Word.h"
#include "functions.h"

Word::Word(char *_word){word=_word;}
bool Word::equals(char* _word){
    cout<<"len of the first word is: "<<len(word)<<" and len of the checked word is: "<<len(_word)<<endl;
    if(len(word)!=len(_word))
        return false;
    else{
    for(int i=0;i<len(word);i++)
        if(word[i]!=_word[i])
            return false;
    }
    return true;

}
char Word::getWord(){
    char *nW = new char[len(word)];
    //cout<<"len of word is:"<<len(word);
    int l=len(word);
    for(int i=0;i<l;i++)
        {
            nW[i]=word[i];
            cout<<nW[i];
    }

    return *nW;

}
void Word::print(char *word){cout<<word;}
void Word::print(){cout<<word<<" ";}

文.cpp

#include "Sentence.h"
#include "Word.h"
#include "functions.h"
Sentence::Sentence()
{

    char* sentence=new char[300];
    cout<<"Entere sentence"<<endl;
    cin.getline(sentence,300);
    int i,j=0,lastIndex=0,count=0;


    int l=len(sentence);
    cout<<"Size of sentence is: "<<l<<"\n";

    for(i=0;i<l;i++){
        //' ' ,'.', ',', '?', ':', '!' ,'\N','\r' ',', '\t', ',', '-'
        if (sentence[i]==' '||
            sentence[i]=='.'||
            sentence[i]==','||
            sentence[i]=='?'||
            sentence[i]==':'||
            sentence[i]=='!'||
            sentence[i]==';'||

            sentence[i]=='-'){
            count++;
            if(count==1)
                {
                    //cout<<subs(sentence,0,i);
                //cout<<"Start Index: 0 and Length is: "<<i<<"\n";
                words[j]=new Word(subs(sentence,0,i));



                    lastIndex=i;

                    j++;
                }
            else{


        //cout<<subs(sentence,lastIndex+1,i-lastIndex-1);
                //cout<<"Start Index: "<<lastIndex+1<<" and Length is: "<<i-lastIndex-1<<"\n";
            words[j]=new Word(subs(sentence,lastIndex+1,i-lastIndex-1));

            lastIndex=i;
            j++;
            }
        }

    }


    if(lastIndex==0){
        //cout<<subs(sentence,0,l);

        words[j]= new Word(subs(sentence,0,l));
    }
    else{
        //cout<<subs(sentence,lastIndex+1,i);
        //cout<<"Start Index: "<<lastIndex+1<<" and length is: "<<i-lastIndex-1<<"\n";
        words[j]= new Word(subs(sentence,lastIndex+1,i-lastIndex-1));

    }
    wordNum=count+1;

}
bool Sentence::containsWord(char* _word){

    for(int i=0;i<200;i++){


        if(words[i]->equals(_word))
                return true;

    }
    return false;

}

int Sentence::getWordNum(char *_word){

    for(int i=0;i<200;i++){
        cout<<words[i]->getWord();
        if(words[i]->equals(_word))
                return i+1;

    }
    return -1;

}
int Sentence::getWords(){return wordNum;}
int Word::getLen(){

    return len(word);
}
4

2 に答える 2

4

関数の実装を に入れているようですfunctions.hそこにプロトタイプを残し、実装を別のファイルに移動しますfunctions.cpp

これでうまくいくはずです。

発生したエラーの説明をもう少し更新してください。

使用#includeすると、コンパイル前にプロセッサによって処理されます (.hファイルをソース ファイルにインライン化するようなものと考えてください)。このプロセスは、すべてのコンパイル単位、つまり.cppファイルに対して発生します (ツリーのルートのように考えてください)。

ここで、インクルード ツリーの「ルート」が異なるため ( A.cpp、 、...)、インクルード ガードは、関数の実装がすべてのコンパイル ユニットにインライン化されるのB.cppを回避するのに役立ちません。

これらの関数には複数の実装があるため、これによりリンク エラーが発生します。

于 2013-07-16T08:17:54.447 に答える
2

各コンパイル単位 (つまり、A.cpp、B.cpp、および C.cpp) には、に含まれる各関数の定義がありますfunctions.h

インクルードガードは、たまたまコンパイル単位の境界内でしか効果がないため、これには役立ちません (つまり、直接的または間接的にfunctions.h、たとえば A.cpp に 2 回インクルードした場合)。

考えられる解決策は次のとおりです。

  1. で関数を宣言しfunctions.h、別のコンパイル単位で定義しますfunctions.cpp(これが例での方法です)
  2. テンプレート関数ですべてfunctions.hの関数を作成します(意味がある場合にのみこれを行います)
  3. のすべての関数をfunctions.h静的であると宣言します (これは単なる回避策であり、そうするように勧めているわけではありません!!!)

PS ポイント 3staticについて。フリー関数を参照する場合、staticキーワードはこの関数をコンパイル単位に対してローカルとしてマークします。したがって、関数はリンク テーブルにエクスポートされず、別のコンパイル ユニット内から呼び出すことはできません。これが、「トリック」が機能する理由です。まだ複数の定義があり、それらはすべて各コンパイル単位に対して「プライベート」であり、競合の可能性はありません。これは、「インターフェイス」の一部ではなく、ローカル ヘルパー関数のみを意図したフリー関数を使用する場合に特に役立ちます。

于 2013-07-16T08:23:13.657 に答える