2

我有三个.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{ .... };” , 出现两次。这是一个错误。

在每个 .h 的顶部和底部添加包含防护是避免此问题的标准做法。别想了。去做就对了。

我建议的另一个更改是从任何 .h 中删除任何“使用命名空间...”行。这打破了命名空间的目的,即把名称放在不同的组中,这样在其他人想要一个具有相同名称的对象或函数的情况下它们就不会模棱两可了。这不是程序中的错误,而是等待发生的错误。

例如,如果我们有:

xstring.h:

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

Foo.h

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

测试.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 中中断。因此,如果您将该头文件提供给某人,则会出现与他们的代码不兼容并且只能通过更改您的头文件并删除“使用命名空间......”来修复的情况。线。

同样,这只是很好的编码风格。别想了。去做就对了。

此外,在我的 Data.h 版本中,我已将方法参数和返回类型更改为引用(使用 &)。这可以防止对象及其所有状态被复制。一些聪明的木屐会指出我们字符串类的实现通过写时复制来防止这种情况。也许是这样,但一般来说,在传递或返回对象时使用引用。它只是更好的编码风格。养成这样做的习惯。

于 2012-10-08T20:09:08.080 回答