我有三个.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'
任何人都可以告诉我这里究竟出了什么问题..
答案 0 :(得分:5)
您需要使用包含警戒,或最简单的:
#pragma once
在您的标题文件中
有关更多背景信息,请参阅Purpose of Header guards
想法:1.hpp
#ifndef HEADER_GUARD_H1_HPP__
#define HEADER_GUARD_H1_HPP__
// proceed to declare ClassOne
#endif // HEADER_GUARD_H1_HPP__
答案 1 :(得分:1)
在每个头文件中写:
#ifndef MYHEADERNAME_H
#define MYHEADERNAME_H
code goes here....
#endif
答案 2 :(得分: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中的include包括:
main.cpp
-> Data.h (1)
-> Point.h
-> Data.h (2)
在(2)处,Data.h已经被粘贴到main.cpp中(1)。数据的类声明,即“类数据{......};” ,出现两次。这是一个错误。
在每个.h的顶部和底部添加包含防护是标准做法,以避免此问题。不要考虑它。就这么做。
我建议的另一个更改是从任何.h中删除任何“using namespace ...”行。这打破了命名空间的目的,即将名称放在单独的组中,以便在其他人想要具有相同名称的对象或函数的情况下,它们不会模糊不清。这不是程序中的错误,但是等待发生错误。
例如,如果我们有:
xstring.h:
namespace xnames
{
class string
{
...
};
}
foo.h中
#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版本中,我已经将方法参数和返回类型更改为引用(使用&amp;)。这可以防止复制对象及其所有状态。一些聪明的clogs将指出我们的字符串类是实现通过写时复制来防止这种情况。也许是这样,但一般来说,在传递或返回对象时使用引用。它只是更好的编码风格。养成做这件事的习惯。