How to include global library in C++ class? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have the main.cpp, a class Student and a global.h library.
I want the functions of global.h to be acessible everywhere, so I did this.
global.h
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
using namespace std;
#ifndef GLOBAL_H
#define GLOBAL_H
int min(vector<int> v) {
int min = -99999999;
for (unsigned int i = 0; i < v.size(); i++) {
if (v[i] > min) min = v[i];
}
return min;
}
double average(vector<int> v) {
int sum = 0;
for (unsigned int i = 0; i < v.size(); i++) {
sum += v[i];
}
return (double)sum / v.size();
}
#endif /* GLOBAL_H */
Student.h
#include "global.h"
#ifndef STUDENT_H
#define STUDENT_H
class Student {
private:
string name;
vector<int> grades;
public:
Student();
void setName(string name);
void addGrade(int grade);
int getBestGrade();
double getAverageGrade();
};
#endif /* STUDENT_H */
Student.cpp
#include "Student.h"
Student::Student() {
}
void Student::setName(string name) {
this->name = name;
}
void Student::addGrade(int grade) {
this->grades.push_back(grade);
}
int Student::getBestGrade() {
return min(this->grades);
}
double Student::getAverageGrade() {
return average(this->grades);
}
main.cpp
#include "Student.h"
using namespace std;
int main(int argc, char** argv) {
Student a;
a.setName("John");
a.addGrade(15);
a.addGrade(13);
a.addGrade(20);
cout << a.getAverageGrade() << endl;
cout << a.getBestGrade() << endl;
return 0;
}
I get this error:
multiple definition of min(...)
multiple definition of average(...)
It seems I am including "global.h" multiple times. But I don't know where. Indeed, I use include "Student.h" two times. But I think the class won't work if I don't to it like this.
Please, help me find out how to include a global library inside a class.
Thanks
##############################
SOLUTION
Thanks to WhiteViking, I have now a solution.
The global.h must have a global.cpp.
global.h
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
using namespace std;
#ifndef GLOBAL_H
#define GLOBAL_H
int min(vector<int> v);
double average(vector<int> v);
#endif /* GLOBAL_H */
global.cpp
#include "global.h"
int min(vector<int> v) {
int min = -99999999;
for (unsigned int i = 0; i < v.size(); i++) {
if (v[i] > min) min = v[i];
}
return min;
}
double average(vector<int> v) {
int sum = 0;
for (unsigned int i = 0; i < v.size(); i++) {
sum += v[i];
}
return (double)sum / v.size();
}

Your question does not show this in detail, but it seems you are defining funcX and funcY in global.h instead of just declaring them.
The preprocessor will replace all #include statements with the verbatim contents of those include files. This happens recursively. So after preprocessing, the compiler sees a "A.cpp" that includes the contents of global.h with the full definitions of funcX and funcY. (global.h was included indirectly via A.h. ) The same thing happens for Main.cpp.
After compilation, the object files for A.cpp as well as for Main.cpp will contain the compiled definitions of funcX and funcY. The error then happens when these object files are linked together in order to build the final executable. The linker will see multiple definitions of these functions and will error out. (It doesn't know/check/care if these definitions are actually identical.)
The solution is to only declare these functions in global.h and put their definition in a separate .cpp file, say global.cpp. For example:
In global.h:
// declarations only here
int funcX(int x);
int funcY(int x);
In global.cpp:
int funcX(int x)
{
return 2 * x;
}
int funcY(int x)
{
return x + 42;
}
In short: you were violating the so-called One Definition Rule (ODR).

Related

Linking a class when used inside another class

When I have a class I want to use somewhere else, such as Secondaryfile.cpp, I can import it fine into another file where I create a new class, as long as I do the class definition, etc inside the .cpp file, not the header file, otherwise I get linking errors. I have tried adding things like extern "C" in the Secondaryfile.cpp but to no avail. Looking at the errors, I also thought that pershaps I shouldn't use the namespace, however, that still results in the same error.
The reason why I am doing this is that I want to import a Tertiaryfile into Mainfile which has a function with the same name as a function in Secondaryfile, so I wanted to be able to refer them as, say, Secondaryfile::add1() and Tertiaryfile::add1() and avoid any issues with the same names that way - through the use of namespaces. I want to be able to declare the Mainfile class in its header file so that I can import it and use it in a different class down the line.
In the example below, running g++ Mainfile2.cpp compiles fine, however, g++ Mainfile.cpp doesn't, instead it results in the following error:
Mainfile.cpp:(.text+0x20): undefined reference to 'Secondaryfile::Secondaryfile::Secondaryfile()'
Mainfile.cpp:(.text+0x58): undefined reference to 'Secondaryfile::Secondaryfile::getX()'
Mainfile.cpp:(.text+0x7a): undefined reference to 'Secondaryfile::Secondaryfile::Secondaryfile(int)'
My code:
Mainfile.cpp
#include "Mainfile.h"
#include <cstddef>
#include <cstdio>
Mainfile::Mainfile(char* name, Secondaryfile::Secondaryfile x)
{
this->name = name;
this->x = x;
}
Mainfile::getDoubleX(){
return this->x.getX() * 2;
}
static Secondaryfile::Secondaryfile getObj(int num){
return Secondaryfile::Secondaryfile(num);
}
int main(){
}
Mainfile.h
#ifndef MAINFILE_H
#define MAINFILE_H
namespace Secondaryfile{
#include "Secondaryfile.h"
}
class Mainfile
{
public:
char* name;
Secondaryfile::Secondaryfile x;
Mainfile(char*, Secondaryfile::Secondaryfile);
int getDoubleX();
static Secondaryfile::Secondaryfile getObj(int);
};
#endif
Mainfile2.cpp
namespace Secondaryfile{
#include "Secondaryfile.h"
}
#include "Mainfile2.h"
#include <cstddef>
#include <cstdio>
class Mainfile2{
public:
char* name;
Secondaryfile::Secondaryfile x;
Mainfile2(char* name, Secondaryfile::Secondaryfile x)
{
this->name = name;
this->x = x;
}
getDoubleX(){
return this->x.getX() * 2;
}
static Secondaryfile::Secondaryfile getObj(int num){
return Secondaryfile::Secondaryfile(num);
}
};
int main(){
}
Mainfile2.h
#ifndef MAINFILE2_H
#define MAINFILE2_H
int getDoubleX();
static Secondaryfile::Secondaryfile getObj(int);
#endif
Secondaryfile.cpp
#include "Secondaryfile.h"
#include <cstddef>
#include <cstdio>
Secondaryfile::Secondaryfile(int x)
{
this->x = x;
}
Secondaryfile::Secondaryfile()
{
this->x = 0;
}
int Secondaryfile::getX()
{
return this->x;
}
int Secondaryfile::add1(int num)
{
return num+1;
}
int main(){
}
Secondaryfile.h
#ifndef SECONDARYFILE_H
#define SECONDARYFILE_H
class Secondaryfile
{
public:
int x;
Secondaryfile();
Secondaryfile(int);
int getX();
static int add1(int);
};
#endif
There are many problems with your code.
In Mainfile.cpp you didn't specify the return type of Mainfile::getDoubleX()(it should be int)
You can only specify static member functions inside a class definition(in Mainfile.cpp, the function getObj has that qualifier). Also it should have a class scope, so the correct way of writing is Secondaryfile Mainfile::getObj(int num)
Doing namespace Secondaryfile{ #include "Secondaryfile.h"}. You shouldn't do this. Just #include "Secondaryfile.h" inside the source files is enough. You mention that you did this to prevent "linking errors", but that is probably because of the other problems in your code and in your project configuration.
You also didn't specify your compiler & IDE/cmake/makefile configs, which is essential for properly compiling and linking these header and source files.
Are you building a library or executable code? You include a main() function in your source files that doesn't do anything, which is also bad practice, because main() in C++ is an entry-point function, wich means that the compiler will look for it to create the starting point of the program1.
With these in mind, I tried to fix your code. See if this is what you had in mind:
Mainfile.cpp
//
// Created by vinicius on 21/10/2020.
//
#include "Mainfile.h"
#include <cstddef>
#include <cstdio>
Mainfile::Mainfile(char* name, Secondaryfile x)
{
this->name = name;
this->x = x;
}
int Mainfile::getDoubleX(){
return this->x.getX() * 2;
}
Secondaryfile Mainfile::getObj(int num){
return Secondaryfile(num);
}
int main() {
//Test code
printf("Hello World!\n--------\n");
Secondaryfile s = Secondaryfile();
Mainfile f = Mainfile("myname", s);
Secondaryfile myobj = f.getObj(12);
printf("Value = %d", myobj.getX());
}
Mainfile.h
//
// Created by vinicius on 21/10/2020.
//
#ifndef MAINFILE_H
#define MAINFILE_H
#include "Secondaryfile.h"
class Mainfile
{
public:
char* name;
Secondaryfile x;
Mainfile(char*, Secondaryfile);
int getDoubleX();
static Secondaryfile getObj(int);
};
#endif
Mainfile2.cpp
//
// Created by vinicius on 21/10/2020.
//
#include "Secondaryfile.h"
#include "Mainfile2.h"
#include <cstddef>
#include <cstdio>
Secondaryfile Mainfile2::getObj(int num) {
return Secondaryfile(num);
}
int Mainfile2::getDoubleX() {
return this->x.getX() * 2;
}
Mainfile2::Mainfile2(char *name, Secondaryfile x) {
this->name = name;
this->x = x;
}
Mainfile2.h
//
// Created by vinicius on 21/10/2020.
//
#ifndef MAINFILE2_H
#define MAINFILE2_H
class Mainfile2{
public:
char* name;
Secondaryfile x;
Mainfile2(char* name, Secondaryfile x);
int getDoubleX();
static Secondaryfile getObj(int num);
};
#endif
Secondaryfile.cpp
//
// Created by vinicius on 21/10/2020.
//
#include "Secondaryfile.h"
#include <cstddef>
#include <cstdio>
Secondaryfile::Secondaryfile(int x)
{
this->x = x;
}
Secondaryfile::Secondaryfile()
{
this->x = 0;
}
int Secondaryfile::getX()
{
return this->x;
}
int Secondaryfile::add1(int num)
{
return num+1;
}
Secondaryfile.h
//
// Created by vinicius on 21/10/2020.
//
#ifndef SECONDARYFILE_H
#define SECONDARYFILE_H
class Secondaryfile
{
public:
int x;
Secondaryfile();
Secondaryfile(int);
int getX();
static int add1(int);
};
#endif
And the CMakeLists.txt for the project(made in CLion):
cmake_minimum_required(VERSION 3.17)
project(secfile)
set(CMAKE_CXX_STANDARD 14)
include_directories(.)
add_executable(secfile
Mainfile.cpp
Mainfile.h
Mainfile2.cpp
Mainfile2.h
Secondaryfile.cpp
Secondaryfile.h)
After building the project with cmake, you can run it. After doing that, it outputs the following lines:
Hello World!
--------
Value = 12
As expected.
1 https://en.cppreference.com/w/cpp/language/main_function

LNK2005 Already Defined error when linking my library [duplicate]

This question already has answers here:
error LNK2005, already defined?
(8 answers)
Closed 3 years ago.
I've made a library when i try and use it in another project i get a LNK2005 error.
Structs.h
#pragma once
#ifndef STRUCTS_H
#define STRUCTS_H
#include <vector>
#include <string>
namespace Structs
{
struct GameObject
{
std::string name;
struct PosPoints
{
double px;
double py;
};
std::vector<PosPoints> Points;
double centroid[2];
bool active;
bool init;
};
std::vector<GameObject> objects;
}
#endif
Structs.cpp
#include "stdafx.h"
#include "Structs.h"
struct Structs::GameObject gameObject;
std::vector<Structs::GameObject> objects;
CoreFuncs.cpp
#include "stdafx.h"
#include "CoreFuncs.h"
#include "Structs.h"
#include <GLFW/glfw3.h>
//render
extern struct Structs::GameObject gameObject;
void RenderShapes()
{
for (int i = 0; i < Structs::objects.size(); i++)
{
for (int j = 0; j < Structs::objects[i].Points.size()-1; j++)
{
glBegin(GL_LINES);
glVertex3f(Structs::objects[i].Points[j].px, Structs::objects[i].Points[j].py, 0);
glVertex3f(Structs::objects[i].Points[j + 1].px, Structs::objects[i].Points[j + 1].py, 0);
glVertex3f(0.1, 0.1, 0);
glVertex3f(0.9, 0.9, 0);
glEnd();
}
}
}
The issue stops happening when i comment out the #include "Structs.h" in CoreFuncs.cpp So I assume that inlcude is what is causing the issues. I have looked around and found many sources using extern but i cant seem to get it working here.
Your header file is declaring an actual variable instance named objects. Every translation unit that #includes your header file will get its own copy of that variable. So when you link multiple such units together into a single executable, you will get errors about all of the duplicate variables.
It looks like you want the variable to be instantiated only once in your Structs.cpp file and then shared by your other units. So the variable needs to be declared as extern in your header file. You should also move the extern declaration of the gameObject variable from out of your CoreFuncs.cpp file and place it in your header file, too.
Structs.h
#pragma once
#ifndef STRUCTS_H
#define STRUCTS_H
#include <vector>
#include <string>
namespace Structs
{
struct GameObject
{
std::string name;
struct PosPoints
{
double px;
double py;
};
std::vector<PosPoints> Points;
double centroid[2];
bool active;
bool init;
};
extern std::vector<GameObject> objects;
extern GameObject gameObject;
}
#endif
Structs.cpp
#include "stdafx.h"
#include "Structs.h"
namespace Structs {
std::vector<GameObject> objects;
GameObject gameObject;
}
CoreFuncs.cpp
#include "stdafx.h"
#include "CoreFuncs.h"
#include "Structs.h"
#include <GLFW/glfw3.h>
//render
void RenderShapes()
{
for (size_t i = 0; i < Structs::objects.size(); ++i)
{
Structs::GameObject &go = Structs::objects[i];
for (size_t j = 0; j < go.Points.size()-1; ++j)
{
PosPoints &pt1 = go.Points[j];
PosPoints &pt2 = go.Points[j + 1];
glBegin(GL_LINES);
glVertex3f(pt1.px, pt1.py, 0);
glVertex3f(pt2.px, pt2.py, 0);
glVertex3f(0.1, 0.1, 0);
glVertex3f(0.9, 0.9, 0);
glEnd();
}
}
}

Expected id-expression - Compiling with g++

I just wrote a program with a Matrix object inside the main.cpp file. Everything was fine.
Now I want to outsource the object into a Matrix.cpp file and Matrix.h header, but I have encountered an error.
I get the following compiler error:
Matrix.cpp:5:15: error: expected id-expression before '(' token
Matrix::Matrix(int n_rows){
Matrix.h:
#ifndef Matrix
#define Matrix
#include "iostream"
#include "string"
#include <sstream>
#include <cstdlib>
using namespace std;
class Matrix{
private:
int n_rows;
int* vect;
public:
Matrix(int);
};
#endif
Matrix.cpp:
#include "Matrix.h"
// Constructor
Matrix::Matrix(int n_rows){ //ERROR
if(n_rows>0){
this->n_rows = n_rows;
this->vect = new int[n_rows];
srand(time(NULL));
for(int i = 0; i< n_rows; i++){
this->vect[i] = rand() % 100;
}
}
}
Maybe there is a keyword to this problem that I do not know jet. I would appreciate it if you could help me out.
NEW: Based on the accepted answer: Why is the the occurence Matrix substituted by a blank space?
#define Matrix means that every occurrence of 'Matrix' will be replaced with nothing by the preprocessor.
Thus, your compiler sees this
using namespace std;
class {
private:
int n_rows;
int* vect;
public:
(int);
};
::(int n_rows){
if(n_rows>0){
this->n_rows = n_rows;
this->vect = new int[n_rows];
srand(time(NULL));
for(int i = 0; i< n_rows; i++){
this->vect[i] = rand() % 100;
}
}
}
But the error message refers to the code before preprocessing, which makes it pretty incomprehensible.
Include guards are conventionally all uppercase (as are macros in general).
You should do that, too.
#ifndef MATRIX_H
#define MATRIX_H

C++ - Can I use extern and const at the same time with several files?

The thing is that I am trying to have a global constant variable for all the .hand .cpp files, but when I do this I got the error:
array bound is not an integer constant before ‘]’ token
I do not understand this because Z is a constant. When I do this with just one file it works. What am I doing wrong?
Number.h
#include <iostream>
extern const int Z;
a.cpp
#include <iostream>
#include "b.h"
#include "c.h"
#include "Number.h"
using namespace std;
int main() {
const int Z = 5;
b Objeto1;
c Objeto2;
double H[Z][Z];
Objeto1.Algo(H);
Objeto2.Imprimir(H);
return 0;
}
b.h
#include <iostream>
#include "Number.h"
class b {
public:
void Algo(double[Z][Z]);
};
b.cpp
#include <iostream>
#include "b.h"
#include "Number.h"
using namespace std;
void b::Algo(double H[Z][Z]) {
for(int a = 0; a < Z; a++) {
for(int b = 0; b < Z; b++) {
H[a][b] = Z;
cout << H[a][b] << endl;
}
}
}
c.h
#include <iostream>
#include "Number.h"
class c {
public:
void Imprimir(double H[Z][Z]);
};
c.cpp
#include <iostream>
#include "c.h"
#include "Number.h"
using namespace std;
void c::Imprimir(double V[Z][Z]) {
cout << "dfs" << endl;
}
I know that the code does not make any sense, but I am just trying to understand how I could have a constant for all the files. I really appreciate your help.
Use of
extern const int Z;
is perfectly fine. However, you can't use Z to define an array. Hence, use of Z in the following line, and similar other lines, is incorrect.
class b{
public:
void Algo(double[Z][Z]);
};
The size of arrays must be known at compiler time. With the extern declaration you have provided, that is not true.
The use of extern const is justified only when you wish to define the value at run time and expect the value to not change until the program ends.
If you simply wish to use it as a token for defining arrays, remove the extern and set its value also. Use:
const int Z = 5;

Error already defined

Hi i just created a sample class and using it in main but i am getting already defined error.
sample.h
#ifndef __sample__
#define __sample__
#include<iostream>
using namespace std;
int count = 10;
class sample
{
public:
sample();
int Get();
private:
int i;
};
#endif
sample.cpp
#include "sample.h"
sample::sample()
{
cout<<"hello two";
}
int sample::sample()
{
return 10;
}
main.cpp
#include <iostream>
#include "sample.h"
using namespace std;
int main(void)
{
int test = count;
return 0;
}
Link error:
main.obj : error LNK2005: "int count" (?count##3HA) already defined in sample.obj
if u see above class i am using #ifndef and #define, actually there things will declare data once thought we include in many places.could some one explain me clearly why its giving that link error.
Remember that #include literally means "add the contents of this file here".
Include guards only protects against a file's content being included more than once per file it's included in.
When the preprocessor has done its preprocessing, this is what your compiler sees:
sample.cpp
[iostream contents here...]
using namespace std;
int count = 10;
class sample
{
public:
sample();
int Get();
private:
int i;
};
sample::sample()
{
cout<<"hello two";
}
int sample::sample()
{
return 10;
}
main.cpp
[iostream contents here...]
using namespace std;
int count = 10;
class sample
{
public:
sample();
int Get();
private:
int i;
};
using namespace std;
int main(void)
{
int test = count;
return 0;
}
As you can see, there are two definitions of count, one in each file (formally, "translation unit").
The solution is to have a declaration of the variable in "sample.h"
extern int count;
and have the one and only definition in sample.cpp:
int count = 10;
(And you should not put using namespace std; in a header.)
To make a global variable like that visible everywhere:
blah.h
extern int count;
blah.cpp
int count(10);
Include guards only guard against including the same header file multiple times, not against multiple definitions. You should move your variable in a cpp file in order to not violate the ODR, or use internal linkage or declare it external and define it somewhere once. There are multiple solutions depending on the use of that variable.
Notice that I'm ignoring the fact that you probably meant int sample::Get() in the sample.cpp file
#include "sample.h"
sample::sample()
{
cout<<"hello two";
}
int sample::sample() // ??
{
return 10;
}
You have either to declare variable count as having internal linkage as for example
#ifndef __sample__
#define __sample__
#include<iostream>
using namespace std;
namespace
{
int count = 10;
}
//...
#endif
(the above internal declaration valid in C++ 2011) or
#ifndef __sample__
#define __sample__
#include<iostream>
using namespace std;
static int count = 10;
//...
#endif
Or to declare it as having external linkage but define it only once in some module. Fpr example
#ifndef __sample__
#define __sample__
#include<iostream>
using namespace std;
extern int count;
//...
#endif
#include "sample.h"
int count = 10;
sample::sample()
{
cout<<"hello two";
}
int sample::sample()
{
return 10;
}
Otherwise the compiler will issue an error that variable count is defined more than once that is that more than one compilation unit (in this case sample.cpp and main.cpp) contain the variable definition.