提问人:ModernEraCaveman 提问时间:9/1/2023 最后编辑:ModernEraCaveman 更新时间:9/3/2023 访问量:121
如何在其他标头中同时使用头文件和 cpp 文件?
How can I use both header files and cpp files within other headers?
问:
我正在 Visual Studio 中处理一个项目,我决定重新组织我的许多代码。不幸的是,我在链接不同的标头及其 cpp 文件时遇到了问题。
我有一个头文件,其中包含通过头文件链传递的库。我不知道这是如何工作的,但我能够让内容填充到所有标题中:
/* vkInstance.h */
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
/* code used other header files */
/* vkGraphicsPipeline.h */
#include "vkInstance.h" // gains access to <GLFW/glfw3.h> within "vkInstance.h"
#include "component.h" // gets access to <GLFW/glfw3.h> through #include "vkInstance.h"
/* other headers similar to component.h */
当组件标头的内容定义位于头文件中时,将定义该文件的元素。组件标头还具有一些宏定义:<GLFW/glfw3.h>
/* component.h */
#ifndef hComponent
#define hComponent
struct exampleStruct {
exampleStruct(/* args */) {
/* constructor code containing <GLFW/glfw3.h> items */
}
void exampleFunc(/* args */) {
/* func code containing <GLFW/glfw3.h> items */
}
}
#endif
虽然定义了上述项目的用法,但我想将许多定义从我的各种头文件移动到它们的 cpp 文件中,这就是我开始遇到问题的地方:<GLFW/glfw3.h>
/* component.h */
#ifndef hComponent
#define hComponent
struct exampleStruct {
exampleStruct(/* args */);
void exampleFunc(/* args */) {
/* func code containing <GLFW/glfw3.h> items */
}
}
#endif
/* component.cpp */
#include "component.h"
exampleStruct::exampleStruct(/* args */) {
/* constructor code containing <GLFW/glfw3.h> items */
}
void exampleStruct::exampleFunc(/* args */) {
/* func code containing <GLFW/glfw3.h> items */
}
虽然我可以访问头文件中的定义,但我无法访问 cpp 文件中的定义,并且程序无法构建。<GLFW/glfw3.h>
我觉得我对C++有很好的掌握,但我远非专家,所以如果我错过了一个明显的解决方案,请原谅我。如何避免此问题和/或更好地组织我的文件结构?
编辑: 很抱歉延迟响应,我已经能够弄清楚如何使用最小可重复的程序复制链接错误(LNK2005、LNK2001 和 LNK2019)。这是它的 github 页面,这里是程序内容的打印输出:
/* main.cpp */
#include "Header2.h"
int main() {
library::object obj;
library::object1 obj1;
library::object2 obj2;
return 0;
}
/* Header.h */
#pragma once // tried with and without, no difference
#include <iostream>
namespace library {
template<typename T>
void print(T input);
void test()
{// definition in the header rather than cpp causes LNK2005,
// but I'm not sure why it does this.
std::cout << "This is a test." << std::endl;
}
struct object {
static inline int i = 1;
object();
~object() = default;
// if I place 'void test()' and it's definition here,
// then I don't get LNK2005
};
}
/* Header.cpp */
#include "Header.h"
library::object::object()
{
std::cout << "I am object!" << std::endl;
}
template<typename T>
void library::print(T input)
{
std::cout << "This is the input: " << input << std::endl;
}
/* Header1.h */
#include "Header.h"
namespace library {
struct object1 {
object1();
~object1() = default;
};
}
/* Header1.cpp */
#include "Header1.h"
#include <iostream>
library::object1::object1()
{
std::cout << "I am object1!\n";
library::print(object::i);
}
/* Header2.h */
#include "Header1.h"
namespace library {
struct object2 {
object2();
~object2() = default;
};
}
/* Header2.cpp */
#include "Header2.h"
// including "Header.h" did not fix LNK2001 or LNK2019
#include <iostream>
library::object2::object2()
{
std::cout << "I am object2!\n";
library::print(object::i);
}
答:
在 cpp+h 示例中,您仍在头文件中定义,现在也在文件中定义。这是违反ODR(单一定义规则)的行为。您需要将头文件更改为简单地声明 ,就像使用构造函数一样。exampleFunc
.cpp
exampleFunc
exampleStruct
此外,由于该文件现在使用 ,因此需要该文件。除非该文件还需要该文件中的内容,否则请将其保留在那里。.cpp
<GLFW/glfw3.h>
#include
.h
#include
尝试更像这样的东西,这取决于实际需要什么:args
组件.h
#ifndef hComponent
#define hComponent
#include <GLFW/glfw3.h>
struct exampleStruct {
exampleStruct(/* args */);
void exampleFunc(/* args */);
};
#endif
component.cpp
#include "component.h"
exampleStruct::exampleStruct(/* args */) {
/* constructor code containing <GLFW/glfw3.h> items */
}
void exampleStruct::exampleFunc(/* args */) {
/* func code containing <GLFW/glfw3.h> items */
}
或者。。。
组件.h
#ifndef hComponent
#define hComponent
struct exampleStruct {
exampleStruct(/* args */);
void exampleFunc(/* args */);
};
#endif
component.cpp
#include "component.h"
#include <GLFW/glfw3.h>
exampleStruct::exampleStruct(/* args */) {
/* constructor code containing <GLFW/glfw3.h> items */
}
void exampleStruct::exampleFunc(/* args */) {
/* func code containing <GLFW/glfw3.h> items */
}
评论
我在这里可能是错的,但你写的代码肯定有一些明显的错误。这里的主要内容在这一部分:
/* vkGraphicsPipeline.h */
#include "vkInstance.h" // gains access to <GLFW/glfw3.h> within "vkInstance.h"
#include "component.h" // gets access to <GLFW/glfw3.h> through #include "vkInstance.h"
/* other headers similar to component.h */
您告诉您将在 vkInstance.h 中包含的 component.h/component.cpp 上访问 glfw 的部分是错误的。包括链条..不是那样工作的。他们就像..一系列标头包含,它传递包含的标头包含的包含。 您应该将 vkInstance.h 包含在 component.h 上,而不是单独的文件上,并期望代码神奇地将包含链接在一起。如果这是真的,那么整个标头链将无效。
试试这个,如果它不起作用,请告诉我:
/* component.h */
#ifndef hComponent
#define hComponent
#include"vkInstance.h"
//this makes sure that vkInstance is included on component.h ,
//which makes it able to include everything that was included
//in vkInstance.h on component.h
struct exampleStruct {
exampleStruct(/* args */);
void exampleFunc(/* args */) {
/* func code containing <GLFW/glfw3.h> items */
}
}
#endif
/* component.cpp */
#include "component.h"
exampleStruct::exampleStruct(/* args */) {
/* constructor code containing <GLFW/glfw3.h> items */
}
void exampleStruct::exampleFunc(/* args */) {
/* func code containing <GLFW/glfw3.h> items */
}
如果可以管理链,则无需一次又一次地包含它们
关于您将遇到的链接器错误,您可能需要尝试将 lib 文件链接到程序。GLFW 在其文件夹之间的某个地方有一个 glfw3.lib 文件。尝试链接它,看看它是否仍然给出错误
祝你好运!!
评论
#include <GLFW/glfw3.h>
#include