Header files. etc - c++

I defined a simple class. The definition is in the header file and the implmentation is in the cpp file:
HEADER:
#ifndef POINT_H
#define POINT_H
class Point {
public:
Point(int x, int y);
int getX();
int getY();
private:
int x, y;
};
#endif
CPP
#include Point.h
Point::Point(int x=2, int y=2) {
this->x = x;
this->y = y;
}
int Point::getX() {
return x;
}
int Point::getY() {
return y;
}
This is not compiling and I am not sure why. Also, when I want to instantiate a point
somewhere else, say main.cpp, what do I #include at the top, just Point.h? If so, how does it know to look in Point.cpp?

#include Point.h
You need quotes around Point.h.
Point::Point(int x=2, int y=2)
The default arguments should be in the declaration in the header file, not in the definition in the .cpp file (it will compile as-is, but won't do what you want).
On a stylistic note, it's usually a bad idea to name local variables or arguments the same as member variables: doing so can easily lead to confusion. You can also initialize member variables using an initializer list:
Point::Point(int x_, int y_) : x(x_), y(y_) { }
As your code is currently written, x and y are both constructed, then you assign to them. Using an initializer list eliminates the assignment and just constructs them directly. This doesn't matter for fundamental types like int, but it does matter for class types.
This is not compiling and I am not sure why.
Usually the error message that the compiler issues is helpful. If nothing else, if it isn't helpful to you, it's helpful to those of us trying to help.
Also, when I want to instantiate a point somewhere else, say main.cpp, what do I #include at the top, just Point.h?
Yes.
How does it know to look in Point.cpp?
Each .cpp file that you write gets compiled into a separate object file. Once all the .cpp files are compiled into object files, the object files all get linked together into an excecutable (or a library). The linker figures out where everything is defined.

You are missing quotes in your include
#include "Point.h"
In the file where you want to instantiate a Point you must include Point.h

You should put the argument defaults in the header although without the error message I can't say if this is your problem. Also you should quote your include #include "Point.h"

You defined default values for x and y in the implementation. This can't work. Think a bit how this is supposed to work if the clients of your class only see the header and hence have no idea that they could possibly call Point without default parameters?
The trick is that the implementation is compiled into your application, and calls get resolved using the declaration only (the stuff in the header). For each call, the compiler creates a symbol name and marks the call (for instance, when you call Point::getX, the compiler will insert call which looks like call _getX#Point#). The linker, which comes after the compiler will search for this function. If it's implemented, it will be found and the caller will get "redirected" to the Point::getX() source code.
[Edit] Oh and you need to write #include "Point.h".

What is the error you're getting?
You just include the .h file:
#include "Point.h"
The linker resolves the references to code when it builds the executable.

Related

C++ defining same function twice causes error

I'm too much confused why it's an error to write the same function in two different cpp files?
what if both want to use that function? and why this should ever cause an error, the function is written in to separate files...
a.cpp:
#include "test.h"
b.cpp:
#include "test.h"
test.h
int getMin(int x,int y)
{
return x;
}
plus, why changing test.h to the following won't fix the problem:
#ifndef UNTITLED1_A_H
#define UNTITLED1_A_H
int getMin(int x,int y)
{
return x;
}
#endif
If you define a function twice, the linker will see 2 definitions of the same function, which is not allowed. (even though each .cpp that includes this header file sees only one definition, which is why adding header guards doesn't help here).
One option is to only write the declaration of the function in the .h file, and write the definition in a separate .cpp file. (this is the more common implementation).
If you want to define the function inside the header file, then it needs to be inline, like this:
inline int getMin(int x,int y)
{
return x;
}
Note that if you do the second option, then all files that include this header will need to be recompiled, if you change the internals of this function (this is probably not a good idea, when the interface doesn't change).
You need to make this function "inline" and it will work.

Clarification on Includes in DLLs

I recently came across something that goes against my understanding of includes.
I am creating a dll to hold basic coordinate objects for a personal game engine I'm developing (for fun).
Main dll header file.
#pragma once
#include "sclapi.h"
#include "vector.h"
#include "point.h"
// Other includes and stuff.
// Unimportant for this demonstration.
sclapi.h
#pragma once
#ifdef SCL_EXPORTS
#define SCL_API __declspec(dllexport)
#else
#define SCL_API __declspec(dllimport)
#endif
vector.h
#pragma once
// No includes
/*EDIT*/struct Point;
struct SCL_API Vector {
float x, y;
// Other stuff
explicit operator Point() const;
};
point.h
#pragma once
// No includes
struct SCL_API Point {
int x, y;
// Other stuff
explicit operator Vector() const;
};
My code works perfectly fine; but to my understanding, it shouldn't. A header file should only know what's declared in it (includes being shorthand for pasting in code). None of these objects are declared in the other's header files. [EDITED] point.h should have no knowledge of a Vector struct. Whats more, both even have knowledge of the SCL_API macro. If I comment out individual includes in the main header file, I get the expected compiler errors. What am I missing?
EDIT:
After further testing, I discovered that a declaration of the later objects needs to be in the first header file 'vector.h'; but after, they do not need to be declared again in any other header file. Also, declaring the classes in the main header file does not work. The Point forward declaration must be inside the vector.h file.
When you #include a file, it gets automatically "copypasted" into your source.
Because you included vector.h right before including point.h, the Point class will see it.
However, it's not a good idea to rely on this behavior as the order of includes might change and thus it will not work anymore, so you should #include "vector.h" in your point.h.

How to Include-guard when using multiple headers on a main.cpp?

I'm learning C++ in a course, using Visual Studio 2013, and I have an issue with include-guards on my main.cpp. I can't use either class or #pragma once (though they work) due to conditions my professor said.
If I only use Coordinates and Line, and I use in main.cpp the #include Line.h (which get code from both Line and Coordinates), this works ok, but when I add Rectangle and Triangle (both have #include "Line.h"), then it throws the "already defined" error LNK2005 several times.
Is there something missing?
This is my code:
Coordinates.h
#ifndef Coordinates
#define Coordinates
//Code declaration. Other headers have similar declaration
struct CoordinatesType { double x, y; } coordinates;
void setCoordinates(double x, double y);
CoordinatesType getCoordinates();
#endif
Coordinates.cpp
#include "Coordinates.h"
//Code implementation
Line.h
#ifndef Line
#define Line
#include "Coordinates.h"
//Code declaration
#endif
Line.cpp
#include "Line.h"
#include <math.h>
//Code implementation
Rectangle.h
#ifndef Rectangle
#define Rectangle
#include "Line.h"
//Code declaration
#endif
Rectangle.cpp
#include "Rectangle.h"
//Code implementation
Triangle.h
#ifndef Triangle
#define Triangle
#include "Line.h"
//Code declaration
#endif
main.cpp
#include "Triangle.h"
#include "Rectangle.h"
int main(){
//Do stuff here.
}
If you need me to add the implementation and declaration codes, let me know, but I feel like it has to do with the include-guard.
EDIT: I'll add code in the Coordinate header so you can get an idea of what I'm doing and to avoid consuming a lot of space in the post. Remember, I can't use class Coordinates{} due to my professor's restriction to not use it.
This error is a linker error, not a compiler error.
Header guards do nothing for the linker.
You have successfully guarded against multiple declarations of things within the same translation unit, but you have not guarded against multiple definitions of things across your whole program.
The way to guard against that is to, well, not do that. There should be no non-inline, non-template definitions of anything in your header if you want to include it into multiple source files.
Here, you declare a type CoordinatesType, and create an object of that type:
struct CoordinatesType { double x, y; } coordinates;
Don't do that! Create an instance of CoordinatesType only in a source file, not in a header. Otherwise, every source file that includes this header (directly or indirectly) will get its own coordinates object and your linker complains about the name collision.
The code should be:
struct CoordinatesType { double x, y; };
Then, either coordinates in the one source file in which you wish to use the object… or extern on its declaration in a header. There are better approaches but I shan't enumerate them all here since this topic has been covered to death on SO already. Furthermore, your C++ book will have an explanation.
But the long and short of it is that this has nothing to do with header guards.
As already pointed out, your problem has nothing to do with include-guards.
Your problem is in this line:
struct CoordinatesType { double x, y; } coordinates;
While the declaration of the struct
struct CoordinatesType { double x, y; };
may appear in multiple .cpp files, as long as it is identical (it is, since you include the same header-file), you also define a variable
CoordinatesType coordinates;
in the same line. Since a definition is only allowed once, your linker complains.
If you really need a global variable of that type (check if you really need one, as it might not be necessary), change your header to a declaration:
struct CoordinatesType { double x, y; };
extern CoordinatesType coordinates;
and use a definition
CoordinatesType coordinates;
in exactly one cpp-file.
Note that the error didn't happen when only including Line and Coordinates, because your include-guards work and you only include the headers in a single .cpp file
Coordinates.h doesn't have any include guard.
When you include it multiple times, it defines Coordinates only once, but the rest of the file is included multiple times.
Put the #endif in the right place.
PS. The identifiers used in the include guards should be something that is never, ever used elsewhere by coincidence. I wouldn't be surprised if someone tried to use a variable named Line or Triangle. And since you #define those, that will lead to very unexpected errors. Use something like #define LineHeader_Included__ .

include header file error: multiple definition

I have a very simple file system in a program.
There is :main.cpp which include worker.h, worker.h and worker.cpp which include worker.h
worker.h has the Header guard and has some variables declared which are required by both main.cpp and worker.cpp and it has some function declarations.
#ifndef __WORKER_H_INCLUDED__
#define __WORKER_H_INCLUDED__
bool x;
int y;
void somefunction( int w, int e );
#endif
Going through some other threads and google results, I understood that the Header guard protects you from multiple inclusions in a single source file, not from multiple source files.
So I can expect linker errors.
My question is
Why there are multiple definition errors for only variables and not for functions ? As far as my understanding goes both of those are only declared and not defined in the header file worker.h
How can I make the a variable available to both main.cpp and worker.cpp without the multiple definition linker error ?
Why there are multiple definition errors for only variables and not for functions ? As far as my understanding goes both of those are only declared and not defined in the header file worker.h
Because you defined the variables. This way they are only declared :
extern bool x;
extern int y;
But you have to define them in a cpp file. :
bool x = true;
int y = 42;
An updated answer for c++17. With the introduction of inline variables, one no longer needs to worry about the exact translation unit where non-const namespace scoped variables need to be placed. Putting aside the discussion about use of global variables in general, another way to fix the OP in modern C++ is to declare the variables as follows:
inline bool x; // Can add an initializer here too
inline int y;
So long as this is in a header and all TU's see the same exact definition, the implementation will resolve it and make sure those TU's all refer to the exact same unique object.

error : multiple definition of constructor

Can you please help me to know how I can avoid the error..
Thanks in advance.
file name: point.hh
#ifndef POINT_H
#define POINT_H
class Point{
private:
int x;
int y;
public:
Point();
};
#endif
file name:point.cc
#include "point.hh"
#include <iostream>
using namespace std;
Point::Point()
{
x=0;
y=0;
cout<<"x="<<x;
cout<<"y="<<y;
}
file name: main.cc
#include"point.cc"
int main()
{
Point p; // calls our default constructor
}
You must include the header file, not the source file, in your main.cc file to use the Point class.
That is, replace:
#include"point.cc"
By:
#include"point.hh"
The rationale behind this is that a function definition, unless marked inline, must respect the ODR ("One Definition Rule"). By including the source file in your other source file, you end up having two (identical) definitions of the Point::Point() function in two different translation units.
When the linking process takes place, it sees this two definitions and complains: that is the error you get.
Another cause is the build command, if you have the same .cpp file listed twice you will definitely get this error and it will say that functions you didn't even write have the error.
Might help someone in the future.