I'm trying to refactor my code, among other things, applying state pattern. I'm more of a Java programmer, so please, be nice ;)
So, here I've got my base state class, nothing fancy:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "FaceRegion.hpp"
class AlghorithmState {
public:
AlghorithmState(FaceRegion context);
virtual ~AlghorithmState();
virtual cv::Mat processImage(cv::Mat frame) = 0;
private:
FaceRegion CONTEXT;
};
and one of child states:
class HaarClassifierState : public AlghorithmState {
public:
HaarClassifierState(FaceRegion context);
virtual ~HaarClassifierState();
cv::Mat processImage(cv::Mat frame);
};
And, then there's Context class, which holds current state and invokes processImage on it inside of its fromImage method/function:
#include "AlghoritmState.hpp"
using namespace cv;
class FaceRegion {
public:
FaceRegion();
virtual ~FaceRegion();
Mat fromImage(Mat& image);
void setAlghoritmState(AlghorithmState state); // line 10
private:
AlghorithmState alghoritm; //line
}
The problem is, when I try compiling this code, I get following error on line 10
In file included from AlghoritmState.hpp:15:0,
from FaceRegion.hpp:10,
from newmain.cpp:93:
FaceRegion.hpp:35:28: error: ‘AlghorithmState’ has not been declared
FaceRegion.hpp:39:5: error: ‘AlghorithmState’ does not name a type
What did I do wrong? I tried adding incomplete class declaration of AlghoritmState in the CONTEXT class header file but it only throws another error:
In file included from AlghoritmState.hpp:15:0,
from FaceRegion.hpp:10,
from newmain.cpp:93:
FaceRegion.hpp:40:21: error: field ‘alghoritm’ has incomplete type
FaceRegion.hpp:36:10: error: cannot declare parameter ‘state’ to be of abstract type ‘AlghorithmState’
In file included from FaceRegion.hpp:10:0,
from newmain.cpp:93:
AlghoritmState.hpp:17:7: note: because the following virtual functions are pure within ‘AlghorithmState’:
AlghoritmState.hpp:21:21: note: virtual cv::Mat AlghorithmState::processImage(cv::Mat)
Any hints appreciated.
You have circular includes here:
AlghoritmState.hpp is #includeing FaceRegion.hpp and vice versa. With include guards this means that one header will see the other, but not the other way.
Your problem is that you use both AlghoritmState in the FaceRegion and the other way around. The AlghoritmState is a interface, so you should drop the member variable there and add it to the implementation, the HaarClassifierState
In that way you include like this:
FaceRegion include AlghoritmState
HaarClassifierState include FaceRegion and AlghoritmState
as you can see, you have no more cycles and you compilation problems will be gone.
Important:
You are currently storing objects by value. When you do that with inherited objects they are prone to slicing which means that you might end up with a object that is smaller that it should be, leading to nasty stuff happening (UB). So you should in all cases stop storing objects super classes as values, and store them as pointers instead.
(which ofcourse leads us to the problems of ownership of the variable, but that is for another question). So only have member variables of a super type if it is the actual super type that is stored there.
Related
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 2 years ago.
So, I know that there are many questions on stack overflow out there that are trying to handle circular dependencies. But none of those could really answer my question, if it is possible to have two classes know each other, and, more importantly, access information from each other. So, basically, I have read that you could use forward decleration, but with forward decleration, I couldn't access any fields. Maybe I should also add that I am really new to C++.But enough talking, let's get to an example:
Let's say we have a class called Scene and a class called EntityBase, which are defined as following:
EntityBase.h
#pragma once
#include <string>
#include "Scene.h"
class EntityBase
{
public:
std::string entityId;
Scene scene;
EntityBase(std::string entityId);
/*
This method will be called when this object is added to the scene
*/
void onAddedToScene(Scene* scene);
/*
This method will be called when this object is removed from the scene
*/
void onRemovedFromScene(Scene* scene);
};
Scene.h
#pragma once
#include <vector>
#include <string>
#include "EntityBase.h"
class Scene
{
public:
std::vector<EntityBase> entities;
std::string name;
Scene(std::string name);
void addToScene(EntityBase& entityBase);
};
The question arises,
How can I print out the name of Scene(and use every method of Scene) while EntityBase can fully access Scene too?
So, I'd really appreciate if you'd tell how to do this, because I will probably need to access every field and/or method later.
Since the C++17 standard you don't need the full EntityBase class definition for the Scene class, only a forward declaration:
#pragma once
#include <vector>
#include <string>
class EntityBase; // Forward declaration
class Scene
{
public:
std::vector<EntityBase> entities;
std::string name;
Scene(std::string name);
void addToScene(EntityBase& entityBase);
};
You of course need to include EntityBase.h anywhere where the entities vector is used, most notable in the Scene.cpp source file.
Since EntityBase is using an actual instance of Scene you can't do the same with that class and the EntityBase.h header file. Here you must include the Scene.h header file.
If you build targeting an older C++ standard (C++14 or earlier) then you must have the full definition of the EntityBase class for the vector.
As a possible workaround either make entities a vector of pointers to EntityBase; Or make EntityBase::scene a pointer and use forward declaration in the EntityBase.h header file instead. Or a combination of both.
Goal: I am making a program which has 10 pattern styles, which are implemented as different classes that derive from a common pattern base class.
The main.cpp creates a pattern style depending on the style chosen by the user.
The question:
how can main know about all pattern styles without creating so many headers?
ex : these will be the files if separated.
baseclass.h
baseclass.cpp
derivedclass1.h
derivedclass1.cpp
derivedclass2.h
derivedclass2.cpp
derivedclass3.h
derivedclass3.cpp
derivedclass4.h
derivedclass4.cpp
main.cpp
inside main.cpp:
#include "derivedclass1.h"
#include "derivedclass2.h"
#include "derivedclass3.h"
#include "derivedclass4.h"
Isn't this too much?
Is there a way to just call 1 namespace which has a list of of all derived class like unity (deriving in monobehavior)? i know it uses c# but still..
=====thoughts=====
Maybe a foreach loop that calls all derived class of the same base class? or should I make a main_header.h which #include all the style and include that from main.cpp?
Include header files, not .cpp files.
If you still need to include .cpp files for some reason: Don't (but rename it to _impl.h etc. for templates)
Instead include header files
#include "derivedclass1.h"
#include "derivedclass2.h"
#include "derivedclass3.h"
#include "derivedclass4.h"
If that seems too much: it is not a sin to put alike classes in the same file (albeit it should be a rare case):
Then include that:
#include "allderivedclasses.h"
Your main concern seems to be "how can main know about all pattern styles?".
The answer is a factory function takes a pattern style name (and maybe some arguments) and produces the correct pattern style object. Each pattern style implementation is responsible for registering itself to the factory, such that main can remain oblivious.
For a more elaborate explanation of this technique, see https://dev.to/fenbf/factory-with-self-registering-types--35h1
In the code below, the PatternStyle class exposes two static functions:
register_pattern: Each sub-class can register its name and a static constructor function at startup time into a std::map pattern_styles.
create: Looks up the name in the std::map and invokes the constructor, if any.
pattern_style.h
class PatternStyle {
...
public:
using Constructor = std::function<std::unique_ptr<PatternStyle>()>;
static std::unique_ptr<PatternStyle> create(const std::string& name);
static bool register_pattern(const std::string& name, Constructor ctor);
};
pattern_style.cpp
static std::map<std::string, PatternStyle::Constructor> pattern_styles;
std::unique_ptr<PatternStyle> PatternStyle::create(const std::string& name) {
auto it = pattern_styles.find(name);
if (it == pattern_styles.cend())
return {};
else
return it->second();
}
bool PatternStyle::register_pattern(const std::string& name, Constructor ctor) {
pattern_styles[name] = ctor;
return true;
}
This allows a subclass to register itself like so:
wavy_pattern_style.h
class WavyPatternStyle : public PatternStyle {};
wavy_pattern_style.cpp
static bool registration = PatternStyle::register_pattern("wavy", std::make_unique<WavyPatternStyle>);
Note: this use of make_unique requires C++14. If you only have C++11, you will need to make a dedicated constructor function (or use a lambda).
With this construct, it is a simple matter of defining pattern styles in separate files and including them in your build system, which solves your secondary concern.
I have the following code, there is an 'Face' class which is composed of an 'Eyebrow' class. The expression of the face can be changed to one of the allowed public enums, thus controlling how each of it's constituent should be changed. Each of the constituent classes should be responsible for responding to a changed expression which is why I want to pass that along to each constituent.
face.h:
#include "eyebrow.h"
class Face {
public:
enum Expression {NEUTRAL, JOY, ANGER};
void setExpression(Expression);
private:
Eyebrow left_eyebrow;
}
face.cpp:
#include "face.h"
#include "eyebrow.h"
void Face::setExpression(Expression e) {
left_eyebrow.setExpression(e);
}
eyebrow.h:
#include "face.h"
class Eyebrow {
public:
void setExpression(Face::Expression);
};
The code is being compiled with Cmake:
add_executable(Main main.cpp face.cpp eyebrow.cpp)
I am getting the following compiler error: ‘Face’ has not been declared in void setExpression(Face::Expression_e) in eyebrow.h.
I then forward declared Face (see below) and got the compiler error: ‘Face::Expression’ has not been declared in void setExpression(Face::Expression); in eyebrow.h
eyebrow.h (with forward declaration):
#include "face.h"
class Face;
class Eyebrow {
public:
void setExpression(Face::Expression);
};
What is the recommended way of solving this, should friends be used?
You have created a circular dependency:
face.h includes eyebrow.h and eyebrow.h includes face.h, so they're including each other. You must resolve the circular dependency.
You could remove the enum from Face and put it in its own header file, which both files could then include.
Alternatively, you could store a pointer to Eyebrow in Face instead of Eyebrow itself. Then you could remove the include of eyebrow.h in face.h and forward-declare Eyebrow instead. The pointer can then be initialized in the constructor of Face.
I'm having issues with my code.
I have a class called Engine:
// Engine.h
#include "SaveLoad.h"
class Engine {
friend void SaveLoad::save(Engine& engine);
friend void SaveLoad::load(Engine& engine);
public:
...
The concern here is I want the functions save() and load() to be able to access and manipulate Engine's private data members freely, which is why I friended them. SaveLoad is actually a namespace in another header file, as shown below:
// SaveLoad.h
#include "Engine.h"
namespace SaveLoad {
void save(Engine& engine);
void load(Engine& engine);
}
All seems fine so far. Next I call the load() function from Engine's constructor to load the application's saved data:
// Engine.cpp
Engine::Engine(...) {
...
SaveLoad::load(*this);
}
I've passed the Engine to the load() function so load() can update Engine's data members when the application is launched.
After compiling, I get literally 22 error messages, some seemingly absurd and others just down right confusing. Some of these errors are:
'Engine' undeclared identifier -- saveload.h
'save' illegal use of type 'void' -- saveload.h
'load' illegal use of type 'void' -- saveload.h
'SaveLoad::save' not a function -- engine.h
'SaveLoad::load' not a function -- engine.h
'SaveLoad' is not a class or a namespace -- engine.h
And directed at the SaveLoad::load(*this) line:
term does not evaluate to a function taking 1 argument -- engine.cpp
I'm guessing this has something to do with the fact that I'm trying to friend functions that are part of a namespace instead of a class or it has something to do with the #includes, but I'm really out of ideas when it comes to playing with the code.
I have multiple classes in my program.
A) When I create an object of a class in another class I am getting no error but when I use the object to call a function I get the above error.
B)Also if I create an object of another class and call a function using that in the constructor of my class then I get no error like this.
C) Cout function does not work in the body of the class except when I put it any function
D) The main class is able to do all of these and I am not getting any error.
It would be great to hear back soon. Thank you in advance.
Following is the code : These are two classes in my cpp. I am facing no problems except using object after creating it. the code is too huge too be posted. Everything can be done in main but not in other classes why?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <vector>
#include <map>
using namespace std;
class Message
{
public:
void check(string side)
{
if(side!="B"&&side!="S")
{
cout<<"Side should be either Buy (B) or Sell (S)"<<endl;;
}
}
};
class Orderbook
{
public:
string side;
Orderbook() //No Error if I define inside constructor
Message m; //No Error while declaring
m.check(side); //Error when I write m. or m->
};
This is a mistake:
m.check(side);
That code has to go inside a function.
Your class definition can only contain declarations and functions.
Classes don't "run", they provide a blueprint for how to make an object.
The line Message m; means that an Orderbook will contain Message called m, if you later create an Orderbook.
Calling m.check(side), meaning you are running actual code, but you can't run code outside main() - you can only define variables.
In C++, code can only appear inside function bodies or in variable initializes.
You can declare an object of a class in another Class,that's possible but you cant initialize that object. For that you need to do something like this :-->
(inside main)
Orderbook o1;
o1.m.check(side)
but that would be unnecessary. Keeping things short :-
You can't call functions inside a Class