What is a fix for a constructor definition error? - c++

So I have a class:
#include "Cool.h"
#include <iostream>
Cool::Cool()
{
//ctor
}
int getVar()
{
int pop = 22;
return pop;
}
and a header file:
#ifndef COOL_H
#define COOL_H
class Cool
{
public:
Cool();
int getVar();
};
#endif
But when I compile, I get an error that says
error: definition of implicitly-declared 'Cool::Cool()'
EDIT:
Don't know if it will help, but I also have a makefile:
program: main.o cool.o
g++ -o program main.o cool.o
cool.o: Cool.cpp Cool.h
g++ -c -o cool.o Cool.cpp
main.o: main.cpp cool.o
g++ main.cpp
EDIT 2: Full Error Message:
Cool.cpp:4:12: error: definition of implicitly-declared ‘Cool::Cool()’
Cool::Cool()
^

This:
cool.o: Cool.cpp Cool.h
g++ Cool.cpp
should be:
cool.o: Cool.cpp Cool.h
g++ -c -o cool.o Cool.cpp
For main.o::
main.o: main.cpp Cool.h
g++ -c -o main.o main.cpp
It is very confusing that you have the same file as both uppercase and lowercase. Does the problem persist after you rename everything to lowercase?

Solved it! I added this to the makefile:
Under main.o:
g++ -c -o main.o main.cpp

Related

C++ undefined reference in Makefile

I created my Makefile for a simple program but it returns undefined reference for class functions constantly:
g++ -c src/main.cpp -o lib/main.o
g++ -c src/functions.cpp -o lib/functions.o
g++ -c src/Circular.cpp -o lib/Circular.o
g++ lib/main.o -o bin/app.exe
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: lib/main.o:main.cpp:(.text+0x20): undefined reference to `Circular::Circular()'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [app.exe] Error 1
Here is my Makefile:
app.exe: lib/main.o lib/Circular.o lib/functions.o
g++ lib/main.o -o bin/app.exe
lib/functions.o: src/functions.cpp
g++ -c src/functions.cpp -o lib/functions.o
lib/Circular.o: src/Circular.cpp
g++ -c src/Circular.cpp -o lib/Circular.o
lib/main.o: src/main.cpp
g++ -c src/main.cpp -o lib/main.o
Here is a short snippet of main.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include "../include/Circular.h"
#include "../include/functions.h"
using namespace std;
int main(int argc, const char * argv[]) {
Circular item;
return 0;
}
Circular.h:
#include "node.h"
class Circular
{
public:
Circular();
node *start;
node *last;
int counter;
}
Circular.cpp:
#include "../include/Circular.h"
#include <iostream>
using namespace std;
Circular::Circular()
{
start = NULL;
last = NULL;
}
and node.h:
struct node
{
int data;
struct node *next;
struct node *prev;
};
I know the problem is about linker and with Makefile but even though I tried different possible solutions, somehow it doesn't work. Therefore, maybe someone can see the mistake I am making. Thanks!
I managed to create a Makefile from this source .
The Makefile looks like this:
CXX = g++
CXXFLAGS = -std=c++17 -Wall
LXXFLAGS = -std=c++17
OBJECTS = main.o Circular.o functions.o
TARGET = main
$(TARGET): $(OBJECTS)
$(CXX) $(LXXFLAG) $(OBJECTS) -o $(TARGET)
main.o: main.cpp Circular.cpp Circular.h functions.cpp functions.h
$(CXX) $(CXXFLAGS) -c main.cpp
Circular.o: Circular.cpp
$(CXX) $(CXXFLAGS) -c Circular.cpp
functions.o: functions.cpp
$(CXX) $(CXXFLAGS) -c functions.cpp
clean:
rm -f $(TARGET) $(OBJECTS)
And also added cout to you Circular constructor to check the execution as below:
#include "Circular.h"
#include <iostream>
using namespace std;
Circular::Circular()
{
start = NULL;
last = NULL;
cout << "Yes!" << endl;
}
Here's the result:
Output
Don't forget to put a semicolon for your Circular class in your Circular.h.
NOTE: If you aren't able to use make in cmd,use choco install make.
The Makefile should be structured to build the dependencies, then the final assembly into a .exe. Each path should be specified exactly as it is, not approximated:
app.exe: lib/main.o lib/Circular.o lib/functions.o
g++ lib/main.o lib/Circular.o lib/functions.o -o app.exe
lib/main.o: src/main.cpp
g++ -c src/main.cpp -o lib/main.o
lib/functions.o: src/functions.cpp
g++ -c src/functions.cpp -o lib/functions.o
lib/Circular.o: src/Circular.cpp
g++ -c src/Circular.cpp -o lib/Circular.o
The key here is be consistent and that includes things like the order of things specified in this file. Whatever order you pick, stick to it. This makes tracking down problems way easier.
If this project gets more complex you probably want to pivot to using a dependency tracking Makefile template instead of this homebrew one. Note how in those you don't need to specify a rule for each file, but instead a rule for each type of file, as in .cpp -> .o, and the rest happens automatically.

Symbol not loaded into templated function

I created a shared library "A" that use an other shared library "B".
I have a problem when I link my program with the shared library "A".
When I use some function from the other shared library ("B") inside cpp file of the shared library "A", all is fine.
But when I use these functions inside .h file (inside a templated method or an inlined method) of the shared library "A", the symbol is not loaded and I get an error "undefined reference to symbol".
I used g++ 7.2.
I think the option -l forget to load the symbols used in header file.
Do you have an idea to avoid this?
Update 2:
Here a full reproducible example:
A.cpp
#include "A.h"
A.h
#ifndef A_H
# define A_H
#include <type_traits>
#include "B.h"
class A
{
public:
template <typename Type>
std::enable_if_t<std::is_arithmetic<Type>::value,void> funcA(Type value);
};
template <typename Type>
std::enable_if_t<std::is_arithmetic<Type>::value,void> A::funcA(Type value)
{
B tmp;
tmp.funcB(value);
}
#endif
B.cpp
#include "B.h"
#include <iostream>
void B::example()
{
std::cout << "works" << std::endl;
}
B.h
#ifndef B_H
# define B_H
class B
{
public:
void funcB(int value);
private:
void example();
};
inline void B::funcB(int value)
{
value += 1;
example();
}
#endif
main.cpp
#include "A.h"
int main()
{
A tmp;
tmp.funcA(5);
return 1;
}
Compile
g++ -std=c++17 -m64 -O2 -DNDEBUG -Wall -Wextra -Werror -fPIC -o A.o -c A.cpp
g++ -std=c++17 -m64 -O2 -DNDEBUG -Wall -Wextra -Werror -fPIC -o B.o -c B.cpp
g++ -std=c++17 -m64 -O2 -DNDEBUG -Wall -Wextra -Werror -fPIC -o main.o -c main.cpp
g++ -o libB.so B.o -shared
g++ -o libA.so A.o -shared -L. -lB
g++ -o application main.o -L . -lA
Error
main.o: In function `main':
main.cpp:(.text.startup+0x1a): undefined reference to `B::example()'
collect2: error: ld returned 1 exit status
Thank you,
SOLVED:
Finally, I solved my problem with this thread:
GCC 4.5 vs 4.4 linking with dependencies
Thank you!

calling c++ function from c

I need to access a C++ function from C but I get some error like :-
/tmp/ccUqcSZT.o: In function `main':
main.c:(.text+0x5): undefined reference to `load_alert_to_db'
collect2: error: ld returned 1 exit status
My main.c code is:-
#include <stdio.h>
extern void load_alert_to_db(void);
int main(void){
/* Create empty queue */
load_alert_to_db();
return 0;
}
C++ code implementation db_manager.cpp is:-
#include <sstream>
#include <iostream>
#include <sstream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <time.h>
#include <cstring>
#include <fstream>
//using namespace oracle::occi;
#include <iostream>
using namespace std;
extern "C" void load_alert_to_db(void)
{
cout<<"db occi"<<endl;
}
makefile is:-
CC= g++
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
clean:
rm -f *.o data
so please help me which one is my problem. I am also include
export LD_LIBRARY_PATH=/home/oracle/Desktop/storage/:$LD_LIBRARY_PATH
environmental variable in .bash_profile
gcc -o data main.c
Not sure why you have this line in your makefile since it will compile main.c without reference to the previously created library and hence cause an undefined-symbol error such as the one you're seeing.
This is especially so, since you appear to have done it the right way on the preceding line:
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
However, the entire point of using makefiles is so that it figures out the minimum necessary commands for you, based on dependencies. Lumping a large swathe of commands into a single rule tends to defeat that purpose. You would be better off making your rules a little more targeted, such as (untested but should be close):
all: data
data: main.o libdb_manager.so
gcc -o data main.o -ldb_manager
main.o: main.c
gcc -o main.o main.c
libdb_manager.so: db_manager.cpp
g++ -c -Wall -Werror -fPIC -o db_manager.o db_manager.cpp
g++ -shared -o libdb_manager.so db_manager.o
That way, if you make a small change to one part (like main.c), it doesn't have to go and compile/link everything in your build tree.
Your makefile seems to be completely broken and random, and you're not even linking the required object files. You can simplify this:
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
to just this:
all:
gcc -Wall -c main.c
g++ -Wall -c db_manager.cpp
g++ main.o db_manager.o -o data
this is what I needed to do:
Supposing the C++ function is called Debug::Write(str)
Then in your hpp file do the following:
#ifdef __cplusplus
extern "C" void DebugTmp(char *str);
#endif
Then in the corresponding cpp file do this:
void DebugTmp(char *str)
{
Debug::Write(str);
}
Then in your C file where you call DebugTmp define the prototype:
void DebugTmp(char *str);
then call it as below:
static void MyFunction( void )
{
DebugTmp("This is debug trace\n");
}

using global new and delete with dynamic lib

I am trying to overload global new and delete. So I have created a separate lib to keep both however when I try to use them i am seeing that my mehotds do not get called. Someone could tell me why and how I could fix, please?
Here is my code:
file my_operator.cpp
#include <cstdlib>
#include <cstdio>
void* operator new(size_t size)
{
puts("constructing");
void* p = malloc(size);
return p;
}
void operator delete(void *p) throw()
{
puts("deleting");
free(p);
}
file myclass.h
class clase
{
private:
int x;
public:
clase(int i):x(i){}
inline int getX(){return x;}
};
main.cpp
#include "myclass.h"
int main()
{
int k = 5;
int ret = 0;
clase* c = new clase(k);
delete c;
return ret;
}
what I have tried so far:
running this:
g++ -c my_operator.cpp -o my_operator.o && g++ main.cpp my_operator.o -o main
then launching ./main --> it works, my operators get called
however
running this:
g++ -c my_operator.cpp -o my_operator.o
ld -o my_operator.so my_operator.o -shared to create the .lib file
and then
g++ main
and finally running ./a.out does not work properly, my operators do not get called
Any clue?
Thanks in advance!
Your commands don't link your main with my_operator.so. You need something like the following:
g++ -Wall -Wextra -c -fPIC -o my_operator.o my_operator.cpp
g++ -shared -o libmy_operator.so my_operator.o
g++ -Wall -Wextra -c -o main.o main.cpp
g++ -o main main.o -lmy_operator
./main
Your main.cpp does not know that you overloaded the operators.
Put your overload operators in the header file.
Usefull links on this matter:
http://en.cppreference.com/w/cpp/memory/new/operator_new
http://www.cprogramming.com/tutorial/operator_new.html

Can't compile the project after splitting the source files to cpp and h, getting "undefined refernce to..."

I had a project, where I had only .cpp files. It worked well, but then I realized, that it's not a good practice, so I decided to split it to .cpp and .h files. Nevetheless now I'm not able to compile the project. Could anybody please look at the source and tell me, where the problem is?
Bot.h
#ifndef BOT_H
#define BOT_H
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;
/**
* Class that represents casual Bot - the parent of other bots
*/
class Bot {
public:
Bot();
virtual ~Bot();
bool initialized;
string getRandomMessage();
string getName();
protected:
vector<string> messages;
string name;
};
#endif /* BOT_H */
Bot.cpp
#include <vector>
#include <string>
#include <cstdlib>
#include "Bot.h"
using namespace std;
string Bot::getRandomMessage() {
int r = static_cast<double> (std::rand()) / RAND_MAX * this->messages.size();
return messages[r];
}
Bot::Bot(){
}
Bot::~Bot(){
}
string Bot::getName() {
return this->name;
}
Example of the class that inherits from the Bot class:
GrumpyBot.h
#ifndef GRUMPYBOT_H
#define GRUMPYBOT_H
#include "Bot.h"
class GrumpyBot : public Bot{
public:
GrumpyBot();
GrumpyBot(const GrumpyBot& orig);
virtual ~GrumpyBot();
};
#endif /* GRUMPYBOT_H */
GrumpyBot.cpp
#include "GrumpyBot.h"
GrumpyBot::GrumpyBot() {
initialized = true;
this->name = "GrumpyBot";
messages.push_back("I hate dogs.");
messages.push_back("I hate cats.");
messages.push_back("I hate goats.");
messages.push_back("I hate humans.");
messages.push_back("I hate you.");
messages.push_back("I hate school.");
messages.push_back("I hate love.");
}
Till now it is ok, but problems appear in the Server.cpp class, where I try to create new instances of those classes and call their functions.
I include there both #include "Bot.h" & #include "GrumpyBot.h" and the compiler keeps getting me messages like /home/ubuntu/NetBeansProjects/SemestralniPraceChat/./Server.cpp:335: undefined reference to 'GrumpyBot::GrumpyBot()'
My makefile looks like this:
#macros
Remove=rm -rf
Doxygen=Doxyfile
RUN=./dvoram64
FLAGS=-Wall -pedantic -Wno-long-long -O0 -ggdb -lncurses -pthread -g
OBJECTS=main.o Bot.o Server.o Client.o
#generates final binary and documentation
all: $(Doxygen)
make compile
#build into final binary
compile: $(RUN)
#run program
run: $(RUN)
$(RUN)
clean:
$(Remove) dvoram64
$(Remove) $(OBJECTS)
#generate documentation in '<login>/doc' folder
doc: $(Doxygen) /*
( cd ./ | doxygen $(Doxygen))
#rules how to compile into the executalble file
$(RUN): $(OBJECTS)
Bot.o: ./Bot.cpp ./Bot.h
g++ $(FLAGS) -c ./Bot.cpp
DummyBot.o: ./DummyBot.cpp ./DummyBot.h ./Bot.h
g++ $(FLAGS) -c ./DummyBot.cpp
GrumpyBot.o: ./GrumpyBot.cpp ./GrumpyBot.h ./Bot.h
g++ $(FLAGS) -c ./GrumpyBot.cpp
JokerBot.o: ./JokerBot.cpp ./JokerBot.h ./Bot.h
g++ $(FLAGS) -c ./JokerBot.cpp
WeatherBot.o: ./WeatherBot.cpp ./WeatherBot.h ./Bot.h
g++ $(FLAGS) -c ./WeatherBot.cpp
Client.o: ./Client.cpp
g++ $(FLAGS) -c ./Client.cpp
main.o: ./main.cpp ./Server.cpp ./Bot.h ./JokerBot.h ./WeatherBot.h ./GrumpyBot.h ./DummyBot.h ./Client.cpp
g++ ./main.cpp $(FLAGS) -o ./dvoram64
Server.o: ./Server.cpp ./Bot.h ./JokerBot.h ./WeatherBot.h ./GrumpyBot.h ./DummyBot.h
g++ $(FLAGS) -c ./Server.cpp
undefined reference is a linker error, you are not passing the objects for the linking process.
In the makefile, replace main.o: lines with
main.o: main.cpp
g++ $(FLAGS) -c main.cpp
remove -lncurses from $(FLAGS) and add:
link: <all the o files>
g++ <all the o files> -lncurses -pthread -o dvoram64
then calling:
make link
will create the correctly linked executable.
Edit:
If you define the $(OBJECTS) variable, the link should be:
link: $(OBJECTS)
g++ $(OBJECTS) -lncurses -pthread -o dvoram64