Duplicate warnings with include guard in Objective-C with C++ header - c++

I have a file iforce2d_topdown_car.h in a demo project with an include guard like so:
#ifndef IFORCE2D_TOPDOWN_CAR_H
#define IFORCE2D_TOPDOWN_CAR_H
... source code ...
#endif
This is included in HelloWorldLayer.h, which is then included in two other files (this is all obj-c except for the iforce2d header). Everything compiles fine, but any errors I get are displayed 3 times. This annoys me, and I wonder if its symptomatic of a larger issue.
Is this expected behavior? It seems to me that if a preprocessor var is defined, then it will stay defined and next time it is included it will not be compiled. It seems that is not the case here, but I do not know why.

The TDCar(b2World *) is an inline member function because it is defined inside its class definition. That means the compiler instantiates the function and emits the corresponding warnings in every translation unit that calls this function.
Let's imagine you have the following A.h:
class A {
public:
int f(int i);
};
and A.cpp
int A::f(int i) {
int j = i;
return i + 1;
}
The compiler will compile the function A::f(int i) once and export it so every call to that function will link to the exported symbol. Therefore, the warning for the unused variable j will be emitted once: when A.cpp is compiled.
But if you write the following A.h:
class A {
public:
int f(int i) {
int j = i;
return i + 1;
}
};
Then the compiler will copy the code from the function definition directly into the source code file that calls the function. If you use that function in 3 different files, the function is compiled thrice and the warning is emitted thrice.
As each file is compiled individually, the compiler cannot know the warning was already emitted for another file.
Xcode should be clever enough to recognize the three warnings as being the same and aggregate them so you only get one warning. Unfortunately, Xcode isn't that clever.

Related

Defined multiple times for the inline function, how possible?

The following quote from c++ primer book confuse me a lot
Unlike other function, inline and constexpr functions may be defined
multiple times in the program. After all, the compiler needs the
definition, not just the declaration, in order to expand the code.
However, all of the definitions of a given inline or constexpr must
match exactly. As a result, inline and constexpr functions normally
are defined in headers.
-- C++ primer 5th Ed, 240 pp
"may be defined multiple times in the program" This quote confuse me a lot. As far as I understand, declaration can be made multiple time, but definition is only needed once.
can someone give me an example why there is a multiple definition.
In a header file (lets call it foo.h) you can have
inline int foo() { /* do stuff */ }
Now if you include foo.h in a couple cpp files then foo will be defined in each of them, which would be a multiple definition error. Since foo is marked as inline though, it is okay because all of the definitions are the same.
As far as I understand, declaration can be made multiple time, but definition is only needed once
The compiler works on translation units (basically a cpp file) and in it, it can do all sorts of optimizations but function inlining and constexpr require that the compiler know the definition of the function. That means each translation unit needs the definition of the function in it. We use inline to make that okay, otherwise it would be a multiple definition error.
As an example. This version isn't valid.
// main.cpp
inline int square(int num) {
return num * num;
}
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
https://godbolt.org/z/nlSbxg
But when you have it in multiple .cpp files (aka. translation units) it is ok because it is now linker job to do right thing.
// b.cpp
inline int square(int num) {
return num * num;
}
// main.cpp
inline int square(int num) {
return num * num;
}
int main()
{
return square(2);
}
Build: gcc main.cpp b.cpp
Same way works #include it will place code in those .cpp files that's all.
Of course if body of function is inlined, then nothing to link so no problem :)
If compiler decides to do an out-of-line version you end up with more than one object file (.o) having definition for the same "inline" function. Such definition will be marked.
Thanks to that mark linker won't yield that it has found multiple definitions and just pick first one that it finds.
So if all definitions are truly the same, then fine! We will get into troubles if we have different body of such function. Example in file b.cpp
// b.cpp
inline int square(int num) {
return 1;
}
It is undefined behavior to have multiple different definitions of the same inline function. It will compile of course but what we get? It depends on linker choice :D
I think the problem is that there are multiple things we can mean by "define." When you write an inline function in a header file, it's "defined" just once in the sense that there is only a single function with that name in your source code.
But that's not how the compiler and linker see the world. If you have an inline function foo in a header file that's called from a.cpp and b.cpp, then the complete compiled version of that function will be included in both a.obj and b.obj. The linker resolves the issue by picking just one of those compiled versions to include in your final binary.
Note that I'm glossing over significant details here, but this is the general idea (and what I think your textbook is eluding to).

Inline function not resolving ambiguity

//myheader.h
namespace abc{
int func(int x) { return 10 + x;}
inline int callfunc(int a){ return func(a); }
}
//global.h
int func(int x){ return 10 + x; }
In the example above, when the code is compiled, and even if the inline function are not called at any place for now, it returns an error to resolve the ambiguity for the func(int x). Why doesn't inline function take the existing definition that is already present in the namespace abc?
Your error is not reproducible from posted code - these headers compile without problems when included in single .cpp file. So you really should post your .cpp files. It's .cpp files that are actually compiled, not headers, so without them we don't get the whole picture.
You should've posted an actual error, not just your impression of it. With your description we can't even be sure if it's compiler error or linker error.
Nevertheless, I'll propose some possible solutions for your problem.
Try to specify namespace in call to the func:
inline int callfunc(int a){ return abc::func(a); }
You really shouldn't define non-inline functions in headers, you'll get linker errors if you include your headers in more than one .cpp file.So you should keep definitions in .cpp and only declarations in .h files like it was meant to be.

Including .cpp files

I have read in places like here that you have to include .h files and not .cpp files, because otherwise then you get an error. So for example
main.cpp
#include <iostream>
#include "foop.h"
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
foop.h
#ifndef FOOP_H
#define FOOP_H
int foo(int a);
#endif
foop.cpp
int foo(int a){
return ++a;
}
works, but if I replace #include "foop.h" with #include "foop.cpp" I get an error (Using Dev C++ 4.9.9.2, Windows):
multiple definition of foo(int)
first defined here
Why is this?
What include does is copying all the contents from the file (which is the argument inside the <> or the "" ), so when the preproccesor finishes its work main.cpp will look like:
// iostream stuff
int foo(int a){
return ++a;
}
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
So foo will be defined in main.cpp, but a definition also exists in foop.cpp, so the compiler "gets confused" because of the function duplication.
There are many reasons to discourage including a .cpp file, but it isn't strictly disallowed. Your example should compile fine.
The problem is probably that you're compiling both main.cpp and foop.cpp, which means two copies of foop.cpp are being linked together. The linker is complaining about the duplication.
When you say #include "foop.cpp", it is as if you had copied the entire contents of foop.cpp and pasted it into main.cpp.
So when you compile main.cpp, the compiler emits a main.obj that contains the executable code for two functions: main and foo.
When you compile foop.cpp itself, the compiler emits a foop.obj that contains the executable code for function foo.
When you link them together, the compiler sees two definitions for function foo (one from main.obj and the other from foop.obj) and complains that you have multiple definitions.
This boils down to a difference between definitions and declarations.
You can declare functions and variables multiple times, in different translation units, or in the same translation unit. Once you declare a function or a variable, you can use it from that point on.
You can define a non-static function or a variable only once in all of your translation units. Defining non-static items more than once causes linker errors.
Headers generally contain declarations; cpp files contain definitions. When you include a file with definitions more than once, you get duplicates during linking.
In your situation one defintion comes from foo.cpp, and the other definition comes from main.cpp, which includes foo.cpp.
Note: if you change foo to be static, you would have no linking errors. Despite the lack of errors, this is not a good thing to do.
You should just include header file(s).
If you include header file, header file automatically finds .cpp file.
--> This process is done by LINKER.
Because of the One Definition Rule (probably1).
In C++, each non-inline object and function must have exactly one definition within the program. By #includeing the file in which foo(int) is defined (the CPP file), it is defined both in every file where foop.cpp is #included, and in foop.cpp itself (assuming foop.cpp is compiled).
You can make a function inline to override this behavior, but I'm not recommending that here. I have never seen a situation where it is necessary or even desirable to #include a CPP file.
There are situations where it is desireable to include a definition of something. This is specially true when you try to seperate the definition of a template from the declaration of it. In those cases, I name the file HPP rather than CPP to denote the difference.
1: "(probably)" I say probably here because the actual code you've posted should compile without errors, but given the compiler error it seems likely that the code you posted isn't exactly the same as the code you're compiling.
Because your program now contains two copies of the foo function, once inside foo.cpp and once inside main.cpp
Think of #include as an instruction to the compiler to copy/paste the contents of that file into your code, so you'll end up with a processed main.cpp that looks like this
#include <iostream> // actually you'll get the contents of the iostream header here, but I'm not going to include it!
int foo(int a){
return ++a;
}
int main(int argc, char *argv[])
{
int x=42;
std::cout << x <<std::endl;
std::cout << foo(x) << std::endl;
return 0;
}
and foo.cpp
int foo(int a){
return ++a;
}
hence the multiple definition error
So I found that if you are compiling from Visual Studios you just have to exclude the included .cpp file from the final build (that which you are extending from):
Visual Studios: .cpp file > right click > properties > configuration properties >
general > excluded from build > yes
I believe you can also exclude the file when compiling from the command line.
I want to clarify something: including header files is not neccessary to make the linker understand what you want. You can just declare it and it will be linked fine.
main.cpp:
#include <iostream.h>
//not including "foop.cpp"!
int foo(int a);
int main(){
std::cout << foo(4) << std::endln;
}
foop.cpp:
int foo(int a){
return a++;
}
I don't encourage doing like this, but know that headers are not some magic which you have to follow to make the code compile.
Using ".h" method is better
But if you really want to include the .cpp file then make foo(int) static in foo.cpp

Multple c++ files causes "multiple definition" error?

I'm using multiple C++ files in one project for the first time. Both have need to include a protected (#ifndef) header file. However, when I do that, I get a multiple definition error.
What I have is two one .cpp file that calls the header directly, and one indirectly (Another include includes it) and then two other header files that include it.
So what do I need to do to get rid of the error?
ERROR:
obj\Debug\main.o||In function Z14sortLibQtyTest4BookS_':|
[PATH]\miscFuncs.h|16|multiple definition ofsortLibQtyTest(Book, Book)'
CODE:
bool sortLibQtyTest(Book a, Book b){ return a.getQty() > b.getQty(); }
It should be mentioned that this isn't the only function giving me problems, probably more than ten are, and some aren't so short and sweet. Also, the functions are needed in multiple files.
You have two options to solve this multiple definition problem: Mark the method inline, or put the definition in a .cpp file.
1) Mark the method inline:
// Foo.h
inline bool foo(int i) { return i = 42; }
2) Put the definition in a .cpp file:
// Foo.h
inline bool foo(int i); // declaration
// Foo.cpp
bool foo(int i) { return i = 42; } // definition
Whether the method is actually inlined by the compiler in the first case is irrelevant here: inline allows you to define a non-member function in a header file without breaking the one definition rule.
The ".cpp" and ".h" suffixes are largely a matter of convention. As far as the compiler is concerned, where a line of code came from is irrelevant. When you #include that function into your .cpp files, you are implementing that function in that .cpp file.
So when the compiler is done and it asks the linker to knit together the code from your two cpp files, it finds a conflict: two functions with the same name and fingerprint (arguments and return). This is an error.
You need to either:
a. Put the implementation in one source file, and just leave a prototype declaration in the header
// .h
extern bool sortLibQtyTest(Book a, Book b);
// file1.cpp
bool sortLibQtyTest(Book a, Book b) { /* implementation */ }
b. Mark the function as inline: when you call the function, the compiler will insert copies of the function body as needed which can be wasteful, but often times the compiler can figure out the efficient thing to do.
inline bool sortLibQtyTest(Book a, Book b) { return a.getQty() < b.getQty(); }
c. Mark the function as "static" which tells the compiler to create a copy of the function for every source file that includes it, but not to expose it to the linker. If some source files include the header without using the function, the compiler has to detect this and remove it - which not all compilers/optimization levels do, so it can be doubly wasteful.
static bool sortLibQtyTest(Book a, Book b) {return a.getQty() < b.getQty(); }
d. Avoid the downsides of c, mark it static inline
static inline bool sortLibQtyTest(Book a, Book b) { return a.getQty() < b.getQty(); }
If the Line you quoted after "CODE" is in a header file you can either:
add inline to the definition or
remove the function body from the header and put it into 1 (and only 1) of your source files.

Function declaration in C and C++

I have two C++ files, say file1.cpp and file2.cpp as
//file1.cpp
#include<cstdio>
void fun(int i)
{
printf("%d\n",i);
}
//file2.cpp
void fun(double);
int main()
{
fun(5);
}
When I compile them and link them as c++ files, I get an error "undefined reference to fun(double)".
But when I do this as C files, I don't get error and 0 is printed instead of 5.
Please explain the reason.
Moreover I want to ask whether we need to declare a function before defining it because
I haven't declared it in file1.cpp but no error comes in compilation.
This is most likely because of function overloading. When compiling with C, the call to fun(double) is translated into a call to the assembly function _fun, which will be linked in at a later stage. The actual definition also has the assembly name _fun, even though it takes an int instead of a double, and the linker will merrily use this when fun(double) is called.
C++ on the other hand mangles the assembly names, so you'll get something like _fun#int for fun(int) and _fun#double for fun(double), in order for overloading to work. The linker will see these have different names and spurt out an error that it can't find the definition for fun(double).
For your second question it is always a good idea to declare function prototypes, generally done in a header, especially if the function is used in multiple files. There should be a warning option for missing prototypes in your compiler, gcc uses -Wmissing-prototypes. Your code would be better if set up like
// file1.hpp
#ifndef FILE1_HPP
#define FILE1_HPP
void fun(int)
#endif
// file1.c
#include "file1.hpp"
...
// file2.c
#include "file1.hpp"
int main()
{
fun(5);
}
You'd then not have multiple conflicting prototypes in your program.
This is because C++ allows you to overload functions and C does not. It is valid to have this in C++:
double fun(int i);
double fun(double i);
...
double fun(int i) { return 1;}
double fun(double i) { return 2.1; }
but not in C.
The reason you aren't able to compile it with your C++ compiler is because the C++ compiler sees the declaration as double and tries to find a definition for it. With the C compiler, you should be getting an error for this as well, I would think you didn't enter the code exactly as you said you did when testing this with the C compiler.
The main point: C++ has function overloading, C does not.
C++ (a sadistic beast, you will agree) likes to mangle the names of the functions. Thus, in your header file for the C part:
at the top:
#ifdef __cplusplus
extern "C" {`
#endif
at the bottom:
#ifdef __cplusplus
}
#endif
This will persuade it not to mangle some of the names.
Look here
OR, in your cpp you could say
extern "C" void fun( double );
A holdover of the C language is that it allows functions to be called without actually requiring the declaration visible within the translation -- it just assumes that the arguments of such functions are all int.
In your example, C++ allows for overloading, and does not support implicit function declarations - the compiler uses the visible function fun(double), and the linker fails because the function fun(double) is never implemented. fun(int) has a different signature (in C++), and exists as a unique symbol, whereas a C compiler (or linker, depending on visibility) would produce an error when you declare both fun(int) and fun(double) as C symbols.
That's just how languages evolved over the years (or not). Your compiler probably has a warning for this problem (implicit function declarations).
You'll see different results when you declare the functions as C functions (they're declared as C++ functions in your example when compiled as C++ source files).
C++ requires the function to be declared before it is used, C does not (unless you tell your compiler to warn you about the issue).
When compiled as C++ you are allowed to have two functions with the same name (as long as they have different parameters). In C++ name mangling is used so the linker can distinguish the two:
fun_int(int x);
fun_double(double x);
When compiled in C there is only one function with a specific name.
When you compile file1.c it generate a function that reads an integer from the stack and prints it.
When you compile file2.c it sees that the fun() takes a double. So it converts the input parameter to a double push it onto the stack then inserts a call to fun() into the code. As the function is in a different compilation unit the actual address is not resolved here but only when the linker is invoked. When the linker is invoked it sees a call to fun needs to be resolved and inserts the correct address, but it has no type information to validate the call with.
At runtime 5 is now converted into a double and pushed onto the stack. Then fun() is invoked. fun() reads an integer from the stack and then prints it. Because a double has a different layout to an integer what will be printed will be implementation defined and depends on how both double and int are layed out in memory.
#include <stdio.h>
int Sum(int j, int f)
{
int k;
k = j + f;
return k;
}
main()
{
int i=3;
int j = 6;
int k = sum(i,j);
printf("%d",k);
}
Output is 9