I am trying to get to grips with inheritance in C++ before trying to implement something in a larger file. I realise this question has been asked before but I've scoured literally everything I could find on this - nothing pointed me towards a fix. So hopefully a kind SO member can help me.
I writing a library for Arduino just to be clear. Here is my code:
CtrlBrd.h
#ifndef CtrlBrd_h
#define CtrlBrd_h
#include "Arduino.h"
class CtrlBrdClass
{
public:
CtrlBrdClass();
};
extern CtrlBrdClass CtrlBrd;
#endif
CtrlBrd.cpp
#include "Arduino.h"
#include "CtrlBrd.h"
CtrlBrdClass::CtrlBrdClass() {
}
int CtrlBrdClass::test()
{
return 79;
}
CtrlBrdClass CtrlBrd;
CtrlBrdEx.h
#ifndef CtrlBrdEx_h
#define CtrlBrdEx_h
#include <CtrlBrd.h>
class CtrlBrdEx : public CtrlBrdClass { // <----- Getting the error here!!
public:
CtrlBrdEx();
int test2();
};
extern CtrlBrdEx CtrlBrd;
#endif
CtrlBrdEx.cpp
#include "CtrlBrdEx.h"
int CtrlBrdEx::test2() {
return CtrlBrd.test() +1;
}
CtrlBrdEx CtrlBrd;
Error:
error: expected class-name before '{' token
Replace
#include <CtrlBrd.h>
with
#include "CtrlBrd.h"
The exact sequence of locations searched by the compiler is implementation dependent in both cases (§16.2 [cpp.include]), but both gcc and VC (and every other compiler if I had to guess) will search the current directory for the quoted form, but not necessarily for the other.
It seems the only solution is to include both files at the top of your main .ino code file. The Arduino compiler doesn't seem to like including libraries from within libraries...
Related
I'm having some troubles where a function isn't returning the right type, because a class isn't defined. I'm using a factory pattern.
The two error messages that I'm getting are:
'return': cannot convert from 'DLA *' to 'Layer *'
and:
'Layer': base class undefined (compiling source file src\Layer.cpp)
and this same error message is repeated for every file that includes Layer.h.
Here is what my class that inherits from Layer looks like (DLA.h):
#pragma once
#ifndef _DLA
#define _DLA
#include "ofMain.h"
#include "ofxGui.h"
#include "Layer.h"
class DLA: public Layer
{
public:
DLA();
void setup();
void update();
void draw();
private:
};
#endif
and here is my Layer class header (Layer.h):
#pragma once
#ifndef _LAYER
#define _LAYER
#include "ofMain.h"
#include "ofxGui.h"
#include "DLA.h"
enum SceneType
{
Scene_None,
Scene_Default,
Scene_DLA,
};
class Layer
{
public:
void setup();
void update();
void draw();
static Layer *CreateSimulation(SceneType Type);
private:
};
#endif
The function which is failing is this one, situated in Layer.cpp:
Layer *Layer::CreateSimulation(SceneType Type)
{
switch (Type)
{
case Scene_None:
default:
return nullptr;
case Scene_DLA:
return new DLA();
}
}
I've tried everything I could find on Stack Overflow that had similar issues to mine but I've seen some people recommend very subtle code indentation to fix this, so I'm really lost as to find where the problem is.
As they stand, your header files induce circular dependency, even though the #pragma once (and other) guards prevent any actual 'infinite recursion'. Let's look at the sequence of code, from the compiler's point-of-view, when compiling the Layer.cpp file (or any other '.cpp' source that has #include "Layer.h" in it).
The compiler encounters #include "Layer.h" (the first time it has done so - the guards won't be 'triggered'), so it duly replaces that line with the contents of the indicated header. In that content, it encounters #include "DLA.h" (we can ignore the other headers included in this discussion, assuming that they aren't relevant to the problem in hand). So, it then duly replaces that line with the contents of the DLA.h header, at which point it will come across this:
#include "Layer.h"
class DLA: public Layer
{
Now, here, when it replaces #include "Layer.h" with the header content, that content will be 'empty' (because of the guards, as it has already included that header once). Thus, when the public Layer code is encountered, it is an error, because that class has not yet been defined, or even declared as a class.
So, if you really insist on having the #include "DLA.h" line in Layer.h, then it must be placed after the definition of the Layer class.
However, a far better way would be to remove #include "DLA.h" from Layer.h, and only place it in source (.cpp) files that actually need it (like Layer.cpp). This would work well:
// Layer.cpp
#include "Layer.h"
#include "DLA.h" // At this point, references to the Layer class in DLA.h will be fine!
//...
Layer *Layer::CreateSimulation(SceneType Type)
{
switch (Type)
{
case Scene_None:
default:
return nullptr;
case Scene_DLA:
return new DLA();
}
}
Feel free to as k for any further clarification and/or explanation.
Please DO NOT make my question as a duplicate. I wanted to force the error to happen!!!! I am not asking how to solve the error. Thank you.
I've heard that if a static member variable is initialised in a header file, and if the header file is included in many different source files, then a link error will occur. And I do believe that.
However, I failed to force the error happen. My program can always be complied successfully. Some say that the include guards prevent the error. It still worked even if I got rid of the include guards.
s1.h
#ifndef S1_H
#define S1_H
class S
{
public:
S();
static int num; // just make it public so that it can be used
};
int S::num = 10;
#endif // S1_H
main.cpp
#include "s1.h"
#include <QDebug>
int main()
{
qDebug() << S::num;
}
test.cpp
#include "s1.h"
#include <QtDebug>
class Test
{
public:
Test();
void printNum() {qDebug() << S::num;}
};
I have three classes.
first class:
#ifndef C_LINKED_LIST_H
#define C_LINKED_LIST_H
class CLinkedList {
private:
//removed code for brevity
public:
// removed code for brevity
};
#endif
second class:
#ifndef C_SSF_FOLDER_CONTAINER_H
#define C_SSF_FOLDER_CONTAINER_H
#include "C_SSF_Folder.h"
#include "CLinkedList.h"
class C_SSF_Folder_Container {
private:
// removed code for brevity
public:
int Add_Folder(C_SSF_Folder *_pcl_SSF_Folder);
C_SSF_Folder *Get_Folder(int _i_Index);
C_SSF_Folder *Get_Folder(char *_pch_Name);
//^-----errors
};
#endif C_SSF_FOLDER_CONTAINER_H
my third class
#ifndef C_SSF_FOLDER_H
#define C_SSF_FOLDER_H
#include <windows.h>
#include <fstream>
#include "C_SSF_Folder_Container.h"
using namespace std;
class C_SSF_Folder {
public:
private:
C_SSF_Folder_Container cl_SSFFC_Folder_Container;
public:
};
#endif
my third class C_SSF_Folder.
I am including "C_SSF_Folder_Container.h"
and declaring a C_SSF_Folder_Container container.
Before declaring the variable it compiles fine. After I declare it
I get syntax errors in my C_SSF_Folder_Container
Severity Code Description Project File Line Suppression State
Error C2061 syntax error: identifier 'C_SSF_Folder' CSSFileSystem\projects\cssfilesystem\cssfilesystem\c_ssf_folder_container.h 16
Error C2061 syntax error: identifier 'C_SSF_Folder' CSSFileSystem \projects\cssfilesystem\cssfilesystem\c_ssf_folder_container.h 19
As I myself look into it I think there is a problem because my C_SSF_Folder is including C_SSF_Folder_Container.
and C_SSF_Folder_Container is including C_SSF_Folder
but the defines should take care of it? Other than that I have no clue what's the problem.
Everything is typed correctly.
You've got a circular #include -- C_SSF_Folder_Container.h #includes C_SSF_Folder.h and C_SSF_Folder.h #includes C_SSF_Folder_Container.h.
This would cause an infinite regress (and a compiler crash) except that you've got the #ifndef/#define guards at the top of your files (as you should); and because of them, instead what you get is that one of those two .h files can't see the other one, and that's why you get those errors.
The only way to fix the problem is to break the circle by deleting one of the two #includes that comprise it. I suggest deleting the #include "C_SSF_Folder.h" from C_SSF_Folder_Container.h and using a forward declaration (e.g. class C_SSF_Folder; instead.
C_SSF_Folder.h and C_SSD_Folder_Container.h are including each other(Circular Dependency).
When the compiler compiles C_SSF_Folder_Container object, it needs to create a C_SSF_Folder object as its field, however, the compiler needs to know the size of C_SSF_Folder object, so it reaches C_SSF_Folder object and tries to construct it. Here is the problem, when the compiler is constructing C_SSF_Folder object, the object has a C_SSF_Folder_Container object as its field, which is a typical chicken and egg question, both files depends on each other in order to compile.
So the correct way to do it is to use a forward declaration to break the circular dependency(including each other).
In your C_SSF_Folder.h, make a forward declaration of C_SSF_Folder_Container.
#include <windows.h>
#include <fstream>
using namespace std;
class C_SSF_Folder_Container;
class C_SSF_Folder {
public:
private:
C_SSF_Folder_Container cl_SSFFC_Folder_Container;
public:
};
#endif
Finally, include C_SSF_Folder_Container.h in your C_SSF_Folder.cpp.
You can also learn more in the following links:
Circular Dependency (Wiki):
https://en.wikipedia.org/wiki/Circular_dependency
Forward Declaration by Scott Langham
What are forward declarations in C++?
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 trouble with my c++ code. I know there is much advices with error "expected class-name before ‘{’ token" but I still can't find where I have it. Here is my sources:
Postava.h
#include <exception>
#include <string>
using namespace std;
#ifndef __Postava_h__
#define __Postava_h__
#include "Barva.h"
#include "Pozice.h"
//#include "Budova.h"
//#include "HerniEngine.h"
#include "GrafickyObjekt.h"
class Budova;
class HerniEngine;
//class GrafickyObjekt;
class Postava;
struct Barva;
struct Pozice;
class Postava:public GrafickyObjekt{ //<----- Here is the error
private:
std::string m_jmeno;
int m_nosnost;
public:
Postava(std::string jmeno, int nosnost);
Budova* m_Budova;
HerniEngine* m_HerniEngine;
std::string vratJmeno();
int vratNosnost();
void vykresli();
};
#endif
GrafickyObjekt.h
#ifndef __GrafickyObjekt_h__
#define __GrafickyObjekt_h__
#include "HerniEngine.h"
#include "Pozice.h"
#include "Posun.h"
class HerniEngine;
class GrafickyObjekt;
class Scena;
struct Pozice;
struct Posun;
class HerniEngine;
class GrafickyObjekt {
protected:
Pozice m_pozice;
public:
HerniEngine* m_HerniEngine;
// kazdy potomek, tj. graf. obj. ma pozici
GrafickyObjekt(Pozice pozice);
// vsichni potomci ji musi implementovat
virtual void vykresli() = 0;
// tyto metody nejsou (ciste) virtualni, budou normalne zdedeny
// tim mam zaruceno, ze vsichni potomci je maji
void pohni(Posun posun);
void pohni(Pozice pozice);
};
#endif
Sorry for my english and for names of classes and names of variables, it's in czech.
Thanks a lot for every advice.
Same answer as in all similar questions asked before:
You created a circular include sequence
It is not obvious from what you posted so far (since you haven't posted all headers). But it is a safe bet that your other header files taken together must produce a circular include "path". More precisely, your GrafickyObjekt.h somehow indirectly includes Postava.h (through other header files that you haven't posted).
The include guards you used in your header files will "break" that cycle in some unpredictable or (better word) unforeseen way. In your case the include guards caused Postava.h to get physically included first, which is why it knows nothing about GrafickyObjekt even though it seems to explicitly include GrafickyObjekt.h. Hence the error.
Circular includes make no sense and achieve nothing. You have to stratify your headers by levels - from low level to high level - and make sure that higher-level headers include lower-level headers, but never the other way around.
Once you achieve that sort of order, you can proceed to resolving circular data dependencies by introducing forward class declarations. I see that you already tried to do that and ended up with a total catastrophic mess, where you basically forward-declare all classes in all headers. Get rid of that mess and start over, by fixing the include stratification first.
It seems that some of your previous includes are faulty.
#include "HerniEngine.h"
#include "Pozice.h"
#include "Posun.h"