I"m having some problem with the following program. The program implements a stack using a linked list. I'm not showing all my code here because the code is fine. But the problem I'm having is with linking different files together.
I'm using an IDE to run the program. When I run the TestIntStacks.cpp, the main method is supposed to call test() from StackFunctions.cpp. The test function (defined in StackFunctions.cpp), uses the TestStack class methods.
Currently I'm receiving an error saying "linker error, push/pop not defined". What I'm doing wrong? I'm sure it's something to do with a namespace.
MyStack.h
-------------------------------------
namespace A
{
class Node{
public :
char data;
StackNode* link;
StackNode(int v=0): data(v), link(NULL){ }
};
class MyStack{
private:
Node * top;
public:
MyStack():top(NULL){ }
void push(int c);
};
}//namespace
//TestStack.cpp
--------------------------------------------------------------
#include "MyStack.h"
namespace A
{
void MyStack::push(int x)
{
StackNode *temp = new StackNode(x);
temp->link = top;
top = temp;
}
}
//StackFunctions.cpp
-----------------------------------------------------------
#include <iostream>
#include "TestStack.h"
using namespace std;
using namespace A;
void test()
{
MyStack st;
st.push(1);
st.push(2);
st.push(3);
st.push(4);
}
// TestIntStacks.cpp
----------------------------------------------------------------
// Code for testing the TestStack
// from the A namespace.
#include <iostream>
#include <vector>
using namespace std;
#include "TestStack"
#include "StackFunctions.cpp"
void test();
int main()
{
test();
system("pause");
return 0;
}
You are defining push() and pop() methods in your header file TestStack.h, but you've not provided implementations for them in TestStack.cpp. You need to add the code that does the push and pop operations on your object.
This error seems pretty clear to me. You declared push() and pop() in your header file, but the linker could not find where these methods are implemented.
Where are they defined?
I think it has to do with the arguments provided to linker. For example, a similar error occurs when you use Visual C++ 6 in a following way. Let's say you created .cpp and .h files for a class. If you do not include cpp file into your project you get the similar error. Because the IDE does not determine the source file based on the provided header file. I don't know about dev-c++ IDE, but the solution might be similar. The problem is you compile (or not) TestStack.cpp and the output of this compiling is not provided to the linker, so the linker can't find the implementation.
You need to force the build script to use both cpp files. If you wrote your own make file, you need to build intermediate objects for each source, and then link at the end.
I suspect DEV-C++ doesnt automatically generate object files or try to link everything together.
Related
I'm comparatively new to C++ so I tested some things out in Xcode, and found a really weird thing.
This is my 'Testing.h' file
#ifndef Testing_h
#define Testing_h
class Testing{
private:
int a;
public:
Testing(int a=3);
void hey(int b);
};
#endif
This is my 'Testing.cpp' file
#include "Testing.h"
Testing::Testing(int a){
a = 4;
}
And finally, this is the 'main.cpp' file
#include <iostream>
#include "Testing.h"
using namespace std;
int main(){
Testing a;
//Apparently not completing the definitions of every abstract methods in the class is not a problem
}
I only declared 'void hey(int b)' in 'Testing.h' but have not defined it in 'Testing.cpp'. So I was wondering how it is possible for the compiler to successfully compile the 'main.cpp' without having enough information of 'void hey(int b)'. Thanks in advance!
Because you never require there to be a definition for hey().
You can require a definition by calling it, for example :
a.hey(42);
And you'll see that the linker isn't too happy because hey is an undefined reference.
Testing a;//Apparently not completing the definitions of every abstract methods in the class is not a problem
You defined constructor with default value a=3 but calling both constructor argument and class parameter the same name is bad practice.
Instead you can write this:
//Testing.h
#ifndef Testing_h
#define Testing_h
using namespace std;
class Testing{
private:
int number;
public:
Testing(int a=3): number(a = 4){}//it's the same as your implementation in cpp file
void hey(int b);
int getNumber() {return number;}
};
#endif
//main.cpp
#include <iostream>
#include "Testing.h"
int main()
{
Testing object;
cout<<object.getNumber();// returns 4
return 0;
}
And why hey compiles?
During building your project compiler translates your source code into object code by verifying the syntax. After that process linker checks the definitions marked by whole phrases. Source code is compiled from each file provided. Linker doesn't care for the implementation presence, it only looks it up if a method is used by the program. So even without implementation of hey your program compiles.
Last remark
It's discouraged to include .cpp files use headers instead. Sometimes you can get yourself into multiple definitions of the same functions causing compiler errors.
Overview
I am trying to develop a C++ application which allows for user-created plugins.
I found a nice library called Pluma (http://pluma-framework.sourceforge.net/) which functionally seems to be exactly what I want.
After going through their tutorial, I was able to (with a bit of difficulty) convince the plugin to compile. However, it refuses to play nice and connect with the main program; returning various errors depending on how I try to implement them.
Problem
If I comment out the line labeled 'Main problem line' (in the last file, main.cpp), the plugin compiles successfully, and the main app can recognize it, but it says that "Nothing registered by plugin 'libRNCypher'", and none of the functions can be called.
If I compile that line, the main application instead says "Failed to load library 'Plugins/libRNCypher.so'. OS returned error: 'Plugins/libRNCypher.so: undefined symbol: _ZTIN5pluma8ProviderE".
My guess is that it has something to do with the way the plugin was compiled, as compiling it initially did not work and Code::Blocks told me to compile with "-fPIC" as a flag (doing so made it compile).
Code
Code below:
Main.cpp
#include "Pluma/Pluma.hpp"
#include "CryptoBase.h"
int main()
{
pluma::Pluma manager;
manager.acceptProviderType< CryptoBaseProvider >();
manager.loadFromFolder("Plugins", true);
std::vector<CryptoBaseProvider*> providers;
manager.getProviders(providers);
return 0;
}
CryptoBase.h
#ifndef CRYPTOBASE_H_INCLUDED
#define CRYPTOBASE_H_INCLUDED
#include "Pluma/Pluma.hpp"
#include <string>
#include <vector>
#include <bitset>
//Base class from which all crypto plug-ins will derive
class CryptoBase
{
public:
CryptoBase();
~CryptoBase();
virtual std::string GetCypherName() const = 0;
virtual std::vector<std::string> GetCryptoRecApps() const = 0;
virtual void HandleData(std::vector< std::bitset<8> > _data) const = 0;
};
PLUMA_PROVIDER_HEADER(CryptoBase)
#endif // CRYPTOBASE_H_INCLUDED
RNCypher.h (This is part of the plugin)
#ifndef RNCYPHER_H_INCLUDED
#define RNCYPHER_H_INCLUDED
#include <string>
#include <vector>
#include <bitset>
#include "../Encoder/Pluma/Pluma.hpp"
#include "../Encoder/CryptoBase.h"
class RNCypher : public CryptoBase
{
public:
std::string GetCypherName() const
{
return "RNCypher";
}
std::vector<std::string> GetCryptoRecApps() const
{
std::vector<std::string> vec;
vec.push_back("Storage");
return vec;
}
void HandleData(std::vector< std::bitset<8> > _data) const
{
char letter = 'v';
_data.clear();
_data.push_back(std::bitset<8>(letter));
return;
}
};
PLUMA_INHERIT_PROVIDER(RNCypher, CryptoBase);
#endif // RNCYPHER_H_INCLUDED
main.cpp (This is part of the plugin)
#include "../Encoder/Pluma/Connector.hpp"
#include "RNCypher.h"
PLUMA_CONNECTOR
bool connect(pluma::Host& host)
{
host.add( new RNCypherProvider() ); //<- Main problem line
return true;
}
Additional Details
I'm compiling on Ubuntu 16.04, using Code::Blocks 16.01.
The second error message seems to not come from Pluma itself, but a file I also had to link, #include <dlfcn.h> (which might be a Linux file?).
I would prefer to use an existing library rather than write my own code as I would like this to be cross-platform. I am, however, open to any suggestions.
Sorry for all of the code, but I believe this is enough to reproduce the error that I am having.
Thank You
Thank you for taking the time to read this, and thank you in advance for your help!
All the best, and happy holidays!
I was not able to reproduce your problem, however looking at
http://pluma-framework.sourceforge.net/documentation/index.htm,
I've noticed that:
in your RNCypher.h file you miss something like
PLUMA_INHERIT_PROVIDER(RNCypher, CryptoBase)
it seems also that there's no file CryptoBase.cpp containing something like
#include "CryptoBase.h"
PLUMA_PROVIDER_SOURCE(CryptoBase, 1, 1);
finally, in CryptoBase.h I would declare a virtual destructor (see Why should I declare a virtual destructor for an abstract class in C++?) and provide a definition to it, while you should not declare a default constructor without providing a definition to it (see for instance Is it correct to use declaration only for empty private constructors in C++?); of course the last consideration is valid unless there's another file in which you have provided such definitions.
I have a query for creating c++ object inside c file.
I have the sample code below. When trying to import the CPlusHeader it throws an error which i could not understand.
The error is iostream' file not found as one of the error. How could i resolve this issue.
Regards,
Lenin
CPlusFile.h
include iostream
include string
using namespace std;
class CPlusFile {
int data;
public:
CPlusFile();
int getData();
};
CPlusFile.cpp
CPlusFIle::CPlusFIle() {
data = 10;
}
int CPlusFile::getData() {
return data;
}
CFile.h
int doSomething();
CFile.c
include "CFile.h"
include "CPlusFile.h"
int doSomething() {
CPlusFile object;
}
It strongly depends on what you call a "C file". Previous answer assumed that you meant a file with a .c suffix. I assume here that you mean a file that shall be compiled with a C compiler.
If my assumption is valid, then the answer is simple: You cannot instantiate C++ classes in a C file. What you can do, though, is call C++ static methods from the C code. Please refer, for example, to In C++ source, what is the effect of extern "C"? to see how to do this.
First of all, it is
#include <iostream>
#include <string>
and not
include iostream
include string
Second, if CFile.c is compiled as C, then this will not work. The C compiler will not understand the class keyword and you cannot create an instance of a class in C.
iostream is a C++ header, and isn't available if you're compiling using a C compiler. You can write C++ code in a .c file, you just need to use the right compiler.
You can use this in your C++ header file to check wether you are going to include it from C or C++ code:
#ifdef __cplusplus
The includes iostream and others, as well as using class, are only available for C++ code.
But if you want to use the CPlusFile class, which is a C++ class, you can only do that in C++ code. Best is to rename your CFile.c to CFile.cpp.
Yes, it is possible to call C++ object inside the C file. Here I performed a scenario and
it's working fine for me.
CPlusFile.h
#include<iostream>
#include<string>
using namespace std;
class cplus{
int data;
public:
cplus();
int getdata();
};
CPlusFile.cpp
#include "cplusfile.h"
cplus::cplus(){ data =10; }
int cplus::getdata(){ return data; }
CFile.h
#include "cplusfile.h"
#include<stdio.h>
int dosomething();
CFile.c
#include "cfile.h"
int dosomething(){
cplus c;
printf("%d",c.getdata());
}
int main() {
dosomething();
return 0;
}
And compile this by g++ CFile.c CPlusFile.cpp and it works fine.
[EDIT:]
The problem seems to belong to the functions, that take default-parameters. Without separating in *.h *.cpp and main file it worked as i implemented something like:
void foo(double db;); // deklaration
void foo(double db = 4){ cout << db;} // definition
int main(){
foo(); // usage
return 1;
}
But if I separate deklaration (-> *.h), definition (-> *.cpp) and usage (-> main) compiling suddenly returns an erro telling, there is no function foo(void), as it does not recognize that there is a default parameter. Any suggestions for that?
[/EDIT]
I wrote a c++-program running somehow like:
#include <iostream>
/* other includes */
using namespace std;
class my_class
{
private:
/* variables */
public:
/* function deklarations (just some short ones are only defined not declared) */
};
ostream& operator<<(ostream &out, my_class member);
/* Definition of the member functions and of the not-member-function */
int main()
{
/*some trial codes of member-functions */
return 1;
}
In one total file all compiled well in Eclipse and worked. Now I also wanted to try seperate in a main,class-header and class-cpp file (called them "my_class.h" and my_class.cpp").
For that i put in class-header:
#ifndef MY_CLASS_H_
#define MY_CLASS_H_
#include <iostream>
/* other includes */
using namespace std;
class my_class
{
/* ... */
};
ostream & operator<<(ostream &out, my_class member);
#endif /* MY_CLASS_H_ */
I put in class-cpp:
/* Definition of the member functions and of the not-member-function */
I put in main:
#include <iostream>
#include "my_class.h"
#include "my_class.cpp"
int main()
{
/*some trial codes of member-functions */
return 1;
}
This version is compiling with the g++ command in commandline:
g++ -o main.exe main.cpp
But it does not Compile in Eclipse. There it gives me the Error:
...\my_class.cpp:11.1: error: 'my_class' does not name a type
and same for all other member functions and variables. I tried to follow the instructions from here (I put just "my_class.h" in main and my_class.cpp, but then it did not compile in Eclipse and in command line (of course then with the my_class.cpp included). Eclipse gives me an Error, that makes me believe Eclipse does not see the "my_class.cpp":
...\main.cpp:288:47: error: no matching function for call to 'my_class::foo(...)'
where foo stands for the first member-function declard in the "my_class.cpp" file. First It gave the error for the constructor too, but as I put it's definition directly into the *.h file it worked well. (That's why I think, it does not see the "my_class.cpp" file)
I think I might be missing something very trivial as I am very new to Eclipse, but I don't see it. I tried to make my questions and information as short as possible.
default-parameters need to be declared in the header-file as it contains the declarations and not in the cpp file, which contains the definitions. (An additional mistake was to declare them in the definition). Found some help here. But why did it work, as I implemented it in one whole file?
Answer:
If default-parameter is in the cpp-file, the main file does not see it as
it looks only into the header-file
But if the whole code is included in just one file, the default-value
can be found in the definition too.
To explain myself:
I considered answering my question, because it gives a better overview of the whole question and the question will now not appear as unanswered. After reading this, I think that it is the right way to do so.
The biggest problem I seem to run into when coding in c++ is the fact that you must declare a class before you can reference it. Say I have two header file like this...
Header1.h
#include "Header2.h"
#include <deque>
#include <string>
#include <iostream>
using namespace std;
class HelloPackage;
class Hello
{
public:
string Message;
HelloPackage * Package;
Hello():Message("")
{
}
Hello(string message, HelloPackage * pack)
{
Message = message;
Package = pack;
}
void Execute()
{
cout << Message << endl;
//HelloPackage->NothingReally doesn't exist.
//this is the issue essentially
Package->NothingReally(8);
}
};
Header2.h
#include "Header1.h"
#include <deque>
#include <string>
#include <iostream>
using namespace std;
class HelloPackage
{
public:
deque<Hello> Hellos;
HelloPackage()
{
Hellos = deque<Hello>();
}
int AddHello(string Message)
{
Hellos.push_back(Hello(Message,this));
}
void ExecuteAll()
{
for each(Hello h in Hellos)
h.Execute();
}
int NothingReally(int y)
{
int a = 0;
a += 1;
return a + y;
}
}
What I'm wondering is, is there any elegant solution for dealing with these issues? In say c#, and java, you're not restricted by this "linear" compiling.
Use header include guards, either "#ifndef / #define / #endif", or "#pragma once"
Put your code in a .cpp, not inline in the header
???
Profit
The reason this will work for you is because you can then use forward declarations of the class you want to reference without including the file if you so wish.
You are missing include guards
why define methods in the header?
Besides these problems with your code, to answer your question : normal way is to forward declare classes - not to include headers in headers (unless you have to).
If you follow a few basic rules, it is not awkward at all. But in comparison to e.g. Java or C#, you have to follow these rules by yourself, the compiler and/or language spec does not enforce it.
Other answers already noted that, but I will recap here so you have it in one place:
Use include guards. They make sure that your header (and thus your class definition) is only included once.
Normally, you will want to separate the declaration and implementation of your methods. This makes the header files more reusable and will reduce compilation time, because the header requires normally fewer #includes than the CPP (i.e. implementation) file.
In the header, use forward declarations instead of includes. This is possible only if you just use the name of the respective type, but don't need to know any "internals". The reason for this is that the forward declaration just tells the compiler that a certain name exists, but not what it contains.
This is a forward declaration of class Bar:
class Bar;
class Foo {
void foooh(Bar * b);
};
Here, the compiler will know that there is a Bar somewhere, but it does not know what members it has.
Use "using namespace xyz" only in CPP files, not in headers.
Allright, here comes your example code, modified to meet these rules. I only show the Hello class, the HelloPackage is to be separated into header and CPP file accordingly.
Hello.h (was Header1.h in your example)
#include <string>
class HelloPackage;
class Hello
{
public:
Hello();
Hello(std::string message, HelloPackage * pack);
void Execute();
private:
string Message;
HelloPackage * Package;
};
Hello.cpp
#include "Hello.h"
#include "HelloPackage.h"
using namespace std;
Hello::Hello() : Message("")
{}
Hello::Hello(string message, HelloPackage * pack)
{
Message = message;
Package = pack;
}
void Hello::Execute()
{
cout << Message << endl;
// Now accessing NothingReally works!
Package->NothingReally(8);
}
One question that may arise is why is the include for string is needed. Couldn't you just forward declare the string class, too?
The difference is that you use the string as embedded member, you don't use a pointer to string. This is ok, but it forces you to use #include, because the compiler must know how much space a string instance needs inside your Hello class.