当我尝试编译代码时遇到了这个问题 我认为这可能是由彼此包括的头文件引起的。但据我所知,我的头文件没有发现任何问题
错误LNK1169一个或多个乘法定义的符号 找到作业2 D:\ 05Development \ 04 C_C ++ \ C \ DS Alg class \ Homework2 \ Debug \ Homework2.exe 1
还有一个错误,告诉我函数Assert()已在其他地方声明。
错误LNK2005“ void __cdecl Assert(bool,class std :: basic_string,class std :: allocator>)“ (?Assert @@ YAX_NV?$ basic_string @ DU?$ char_traits @ D @ std @@ V?$ allocator @ D @ 2 @@ std @@@ Z) 已在DataBase.obj Homework2 D中定义:D:\ 05Development \ 04 C_C ++ \ C \ DS Alg类\ Homework2 \ Homework2 \ dbTest.obj 1
这是我的代码的结构:
功能
void Assert(bool val, string s)
{
if (!val)
{
cout << "Assertion Failed!!: " << s << endl;
exit(-1);
}
}
位于Constants.h
虚拟类列表包含Constants.h
#pragma once // List.h
#include "Constants.h"
一个数组列表包括List类,在AList类中它调用了Assert函数
#pragma once //AList.h
#include "List.h"
...
Assert((pos >= 0) && (pos < listSize), "Position out of range");
在数据库类中,我创建了一个AList成员
private:
AList<CData> set;
标题看起来像这样: #pragma一次 #include“ AList.h” #include“ CData.h”
和CData.h看起来像这样:
#pragma once
class CData
{
private:
std::string m_name;
int m_x;
int m_y;
public:
CData(std::string str = "null", int x = 0, int y = 0) : m_name(str), m_x(x), m_y(y) {}
// Helper functions
const std::string& GetName() const { return this->m_name; }
const int& GetX() const { return this->m_x; }
const int& GetY() const { return this->m_y; }
};
答案 0 :(得分:3)
在生成项目时,每个.cpp文件都会分别编译为不同的目标文件。 once
中的#pragma once
仅适用于单个.cpp文件的编译,不适用于整个项目。因此,如果.cpp文件包含标头A和标头B,并且标头B也包含标头A,则将跳过标头A的第二个包含。
但是,如果您还有另一个包含A的.cpp文件,则A将再次包含在该目标文件中-因为#pragma once
仅在编译单个.cpp文件时有效。
#include语句从字面上获取包含文件的内容,并将其“粘贴”到包含该文件的文件中。您可以通过查看C预处理程序工具(cpp
工具链中的gcc
)的输出来进行尝试。如果您使用的是gcc工具链,则可以在应用包含文件后尝试执行以下操作来查看该文件:
cpp file.cpp -o file_with_includes.cpp
如果标头中有一个函数(例如示例中的Assert
),该函数将复制到包含它的每个.cpp文件中。
如果具有A.cpp和B.cpp,它们都包含Constants.h文件,则每个目标文件(.o或.obj取决于您的环境)将包含Assert函数的副本。当链接程序组合目标文件以创建二进制文件时,两个目标文件都将声明它们提供了Assert的定义,并且链接程序会抱怨,因为它不知道使用哪个。
这里的解决方案是内联您的Assert函数,如下所示:
inline void Assert(bool val, string s)
{
if (!val)
{
cout << "Assertion Failed!!: " << s << endl;
exit(-1);
}
}
或在其自己的.cpp文件中提供其主体,而仅在标头中保留函数原型。
Constants.h:
void Assert(bool val, string s);
Constants.cpp:
void Assert(bool val, string s)
{
if (!val)
{
cout << "Assertion Failed!!: " << s << endl;
exit(-1);
}
}
请记住,标准库还提供assert()
,它也很好用。 (请参阅https://en.cppreference.com/w/cpp/error/assert)。
#include <cassert>
...
assert(is_my_condition_true());
assert(my_variable > 23);
// etc..
请记住,cassert
中声明的断言仅在为Debug编译时有效,而在为Release发行时被编译出去(以加快执行速度),因此请不要在具有副作用。
#include <cassert>
...
// Don't call functions with side effects.
// Thus function decreases a "count" and returns the new value
// In Release builds, this line will disappear and the decrement
// won't occur.
assert(myclass.decrement_count() > 0);