2

私は3つの.cppファイルを取得し、two header files.

しかし、それらをコンパイルすると、つまり Point.cpp、Data.cpp、main.cpp と表示されます。

Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'

以下は私のData.hです(以前は上記の2.hとして知られていました)

#include <iostream>
#include <string>

using namespace std;

class Data
{
private:
string sType;
public:
Data();
Data(string);
void setSType(string);
string getSType();
};

以下は私のdata.cppです

#include "Data.h"

Data::Data()
{
sType = "";
}

Data::Data(string s)
{
sType = s;
}

void Data::setSType(string ss)
{
sType = ss;
}

string Data::getSType()
{
return sType;
}

以下は私の PointD.h (以前は 3.h として知られていた) です。

#include <iostream>
#include <string>
#include "Data.h"

using namespace std;

class PointD
{
private:
int x
Data data1;
public:
PointD();
PointD(int,Data);

void setX(int);
void setData(Data);

int getX();
Data getData();
};

以下は私のPointD.cppです

#include "PointD.h"

PointD::PointD()
{
x = 0;
}

PointD::PointD(int xOrdinate,Data dd)
{
x = xOrdinate;
data1 = dd;
}

void PointD::setXordinate(int Xordinate)
{
x = Xordinate;
}

void PointD::setData(Data dd)
{
data1 = dd;
};

int PointD::getXordinate()
{
return x;
}

Data PointD::getData()
{
return data1;
}

これは私のmain.cppです

#include <iostream>
#include <string>

#include "Data.h"
#include "PointD.h"
using namespace std;

int main()
{
const int MAX_NUM = 20;

Data ldata[MAX_NUM];
PointD pointd[MAX_NUM];

//more codes..
}

しかし、それらをコンパイルすると、つまり Point.cpp、Data.cpp、main.cpp と表示されます。

Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'

ここで実際に何がうまくいかなかったのか、誰か教えてもらえますか..

4

3 に答える 3

5

インクルードガードを使用する必要があります。または最も簡単な方法です。

 #pragma once

ヘッダーファイル内

詳細については、ヘッダーガードの目的を参照してください。

アイデア:1.hpp

#ifndef HEADER_GUARD_H1_HPP__
#define HEADER_GUARD_H1_HPP__

// proceed to declare ClassOne

#endif // HEADER_GUARD_H1_HPP__
于 2012-10-08T17:07:25.960 に答える
1

各ヘッダー ファイルに次のように記述します。

#ifndef MYHEADERNAME_H
#define MYHEADERNAME_H

code goes here....

#endif
于 2012-10-08T17:12:52.803 に答える
1

次のようにします。

#ifndef DATA_H    /* Added */
#define DATA_H    /* Added */

#include <iostream>
#include <string>

// using namespace std;  /* Removed */

class Data
{
private:
   std::string sType;
public:
   Data();
   Data( std::string const& );          // Prevent copy of string object.
   void setSType( std::string& );       // Prevent copy of string object.
   std::string const& getSType() const; // prevent copy on return
   std::string& getSType();             // prevent copy on return
};

#endif /* DATA_H */

大きな修正は、ifndef,define,endif の追加です。#include ディレクティブは、.h をコピーしてその行に貼り付けたかのように機能します。あなたの場合、main.cpp からのインクルードは次のとおりです。

   main.cpp
     -> Data.h  (1)
     -> Point.h
        -> Data.h (2)

(2) で、Data.h は既に (1) で main.cpp に「貼り付け」られています。Data のクラス宣言、つまり「class Data{ .... };」、2 回表示されます。これはエラーです。

この問題を回避するために、すべての .h の上部と下部にインクルード ガードを追加するのが標準的な方法です。考えないでください。早くやれよ。

私が提案するもう1つの変更は、すべての .h から「using namespace ...」行を削除することです。これは、他の誰かが同じ名前のオブジェクトまたは関数を必要とする場合にあいまいにならないように、名前を別々のグループに配置するという名前空間の目的を破ります。これはプログラムのエラーではありませんが、発生するのを待っているエラーです。

たとえば、次の場合:

xstring.h:

namespace xnames
{
    class string
    {
        ...
    };
}

フー。

#include <xstring>
using namespace xnames;
...

test.cxx:

#include "Foo.h"  
#include "Data.h"    // Breaks at:   Data( string );  -- std::string or xnames::string?

...
void test()
{
   string x;  // Breaks.  // std::string or xnames::string?
}

ここで、コンパイラは xnames::string と std::string のどちらを意味するのかを認識しなくなります。これは test.cxx で失敗します。これは、より具体的にすることで修正できます。

void test()
{
   std::string x;
}

ただし、このコンパイルは現在も Data.h で壊れています。したがって、そのヘッダー ファイルを誰かに提供すると、コードと互換性がなくなり、ヘッダー ファイルを変更して「using namespace ...;」を削除することによってのみ修正できる場合があります。行。

繰り返しますが、これは優れたコーディング スタイルです。考えないでください。早くやれよ。

また、私のバージョンの Data.h では、メソッドのパラメーターと戻り値の型を参照 (& を使用) に変更しました。これにより、オブジェクトとそのすべての状態がコピーされなくなります。一部の巧妙な詰まりは、文字列クラスの実装がコピーオンライトであるため、これを防止していることを指摘します。そうかもしれませんが、一般的には、オブジェクトを渡したり返したりするときに参照を使用します。コーディングスタイルが優れているだけです。それをする習慣を身につけてください。

于 2012-10-08T20:09:08.080 に答える