I am working on a project in Visual Studio and I decided to reorganize a lot of my code. Unfortunately, I am running into problems with linking different headers and their cpp files.
I have one header file that contains the libraries which get passed down a chain of header files. I have no idea how this works, but I am able to get the contents to populate throughout all of the headers:
/* 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 */
When the component header's content definitions are within the header file, elements of the <GLFW/glfw3.h> file are defined. The component header also has some macro definitions:
/* 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
While the above usage of <GLFW/glfw3.h> items is defined, I would like to move a lot of the definitions from my various header files to their cpp files, and that's where I start to run into problems:
/* 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 */
}
Whereas I had access to <GLFW/glfw3.h> definitions in the header file, I lose access to them in the cpp file, and the program fails to build.
I feel like I have a decent grasp on C++, but I am far from an expert, so please forgive me if I am missing an obvious solution. How can I avoid this problem and/or better organize my file structure?
Edit: Sorry for the delayed response, I've been able to figure out how to replicate the linking errors (LNK2005, LNK2001, and LNK2019) with a minimally reproducible program. This is a github page for it and here is a printout of the program contents:
/* 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);
}
In your cpp+h example, you are still defining
exampleFuncin your header file, AND now in your.cppfile too. That is an ODR (One Definition Rule) violation. You need to change your header file to simply declareexampleFunc, just like you did with theexampleStructconstructor.Also, since the
.cppfile now uses things from<GLFW/glfw3.h>, it needs to#includethat file. Unless the.hfile also needs things from that file, then leave the#includethere instead.Try something more like this, depending on what
argsactually need:component.h
component.cpp
Alternatively...
component.h
component.cpp