Weird Class/Function File Interaction

I have a weird problem that only appears when I split the program into multiple files and pass by reference. Let's say I have 4 files:

main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
#include <iostream>
#include "Rectangle.h"
#include "Function.cpp"

using namespace std;

int main() {
	Rectangle rect;
	rect.height = 0;
	someF(rect);
	cout << "h =  " << rect.height << endl;
	return 0;
}


2 files for a class called Rectangle:
Rectangle.h:
1
2
3
4
5
6
class Rectangle {
public:
	int width, height;
	void set_values(int, int);
	int area() { return width*height; }
};


Rectangle.cpp:
1
2
3
4
5
6
#pragma once
#include "Rectangle.h"
void Rectangle::set_values(int x, int y) {
	width = x;
	height = y;
}


And a function in its own file:
Function.cpp
1
2
3
4
5
6
#pragma once
#include "Rectangle.h"

void someF(Rectangle &myrect){
	myrect.height = 5;
}


This works fine when the function someF is placed in main, it also works fine in its own file if I passed myrect by pointer to it instead of by reference, but it does not work when it's a pass by reference - or by value - in its own file, it gives an error:
"main.obj : error LNK2005: "void __cdecl someF(class Rectangle &)" (?someF@@YAXAAVRectangle@@@Z) already defined in Function.obj"
Last edited on
I don't think that that is the way the pragma once should be used. That is your main error.

One should not include .cpp-files. The convention is to compile each .cpp separately and they merely include necessary declarations and definitions that are in header files.

Yeah, I know. I tried #ifndef with the same result, I just added #pragma once in everything because I started to get desperate and started trying everything.

My original problem was a 5000+ project where this problem happens between 2 huge classes, this is just a stripped down version just to have a minimal code for the question.
Your IDE is probably set up so that it compiles each .cpp file and then links them all together. This would lead to someF being defined multiple times, once for Function.cpp, and once for main.cpp because it includes Function.cpp.

You should never have to include .cpp files. Instead create a header file that declares the function and include that instead.

Function.h
1
2
3
4
#pragma once
#include "Rectangle.h"

void someF(Rectangle &myrect);


Function.cpp
1
2
3
4
5
#include "Function.h"

void someF(Rectangle &myrect){
	myrect.height = 5;
}


main.cpp
1
2
3
4
5
6
7
8
9
#include <iostream>
#include "Rectangle.h"
#include "Function.h"

using namespace std;

int main() {
	...
}

Last edited on
Weird, still does not work, I'm using Visual Studio 2015 which is pretty finicky sometime.
Ok, the issue turned out to be VS is as weird and confusing as always, it's a debug build only error that does not happen in release build, and I really doubt it will fail in other compilers. God I hate this stupid IDE and compiler sometimes.

Adding "/FORCE:MULTIPLE" to the debug linker command line options solves it for debug mode.
Last edited on
If you were doing things correctly you wouldn't need to use FORCE:MULTIPLE. You're probably still including a .cpp file somewhere or are defining (non-inline) functions in .h files.
I don't think I do, I'm not sure about the non-inline part. Here's all the final files:

I have a weird problem that only appears when I split the program into multiple files and pass by reference. Let's say I have 4 files:

main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
#include "stdafx.h"
#include <iostream>
#include "Rectangle.hpp"
#include "Function.hpp"

using namespace std;

int main() {
	Rectangle rect;
	rect.height = 0;
	someF(rect);
	cout << "h =  " << rect.height << endl;
	return 0;
}


Rectangle.hpp:
1
2
3
4
5
6
7
#pragma once
class Rectangle {
public:
	int width, height;
	void set_values(int, int);
	int area() { return width*height; }
};


Rectangle.cpp:
1
2
3
4
5
6
#include "Rectangle.hpp"

void Rectangle::set_values(int x, int y) {
	width = x;
	height = y;
}


Function.hpp
1
2
3
#pragma once
#include "Rectangle.hpp"
void someF(Rectangle &myrect);



Function.cpp
1
2
3
4
#include "Function.hpp"
void someF(Rectangle &myrect){
	myrect.height = 4;
}


This only works with /FORCE:MULTIPLE on debug.
Last edited on
All I can think of is if there's something strange in stdafx.h. Otherwise I don't see anything wrong. The only thing I can suggest is to start a whole new project and see if that fixes it, but you probably already did that.

Are you saying that if you change Function.hpp and Function.cpp so that someF takes the Rectangle by value (which won't change it in main, of course) then it works without FORCE:MULTIPLE?

BTW, "pragma once" doesn't do anything in a cpp file, so you should take it out of main.cpp.
Have you tried doing a clean build?
+1 for clean


A note about dependencies:
The declaration of someF does not need to know Rectangle;
it is sufficient to know that identifier "Rectangle" is a class.

Function.hpp
1
2
3
#pragma once
class Rectangle; // forward declaration
void someF( Rectangle &myrect );


The implementation has to know the full class definition:
Function.cpp
1
2
3
4
5
6
7
#include "Function.hpp"
#include "Rectangle.hpp"

void someF( Rectangle &myrect )
{
	myrect.height = 4;
}
Last edited on
Ok, scratch the /FORCE:MULTIPLE part, it does nothing, VS is even dumber than I thought. To make it work, build the solution, it will fail and give the error, now do any dummy change to the Function.cpp file, like adding a useless line or space, and now it will build and run fine.

By the way, the exact files build fine in other IDEs without the nonsense, and I always use clean when I get weird errors, it's does not solve the problem.
Last edited on
VS is one of the best IDEs. You probably had pre-built stuff that the project thought didn't need to be rebuilt, so regular builds would continue to have linker errors. Perhaps you didn't "Rebuild" one such dependency (adding characters made it think otherwise).
VS is even dumber than I thought

I'm no fan, but it's very dumb for you to think this. You haven't found the problem yet.
99.999% of the time when a beginner complains about "weird" something-or-other, they are blaming the system for their own mistake.
Last edited on
touch is your friend if the IDE is really not working right. But rebuild all has never failed me in vs, double check which build you are hitting.
VS is dumb, I had too many dumb things happen that does not happen on any other IDE, I only use it because of its great debugger. Tell me when you find the problem cause I'm pretty sure it's an internal VS linker bug, it works fine in other IDEs and it works in VS when I add a useless space, that is pretty Goddamn dumb.
Last edited on
Topic archived. No new replies allowed.