C++ friend a function in a separate namespace - c++

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.

Related

JsonDocument was not declared in this scope when delcaring a function

I'm trying to write a simple API view using ESP32 and Arduino IDE and I've run into this problem. When I declare a handler (function) the usual way, the compiler fails with 'JsonDocument' was not declared in this scope, but when I split declaration and implementation, it works ok. What is causing it and how to work around it?
This fails:
// Provides JsonDocument class
#include <ArduinoJson.h>
void handleApi(JsonDocument& doc){}
This works:
// Provides JsonDocument class
#include <ArduinoJson.h>
void handleApi(JsonDocument& doc);
void handleApi(JsonDocument& doc){}

pre-defining classes not working when using pointers to classes

I am trying to implement a listener. Because of many cross-references I am trying to avoid including other classes and pre-define them
My listener looks as follows
.h
class Book
{
public:
Book();
private:
std::vector<MyListener *> listeners_;
void Notify();
}
.cpp
Book::Book() {}
void Book::Notify() {
MyListener *p_listener;
for ( int i = 0; i < this->listeners_.size(); i++ ) {
p_listener = listeners_[i];
p_listener->Update(); // ERRORS THROWN HERE WHEN NOT INCLUDING LISTENER.H
}
}
This all works fine when I include the listener.h file
#include "listener.h"
But when I instead pre-declare Listener it doesnt work
class Listener;
It gives me the two errors
C:\CPP\qtTradeSim\qtTradeSim\test\book.cpp:33: error: C2027: use of undefined type 'Listener'
C:\CPP\qtTradeSim\qtTradeSim\test\book.cpp:33: error: C2227: left of '->Update' must point to class/struct/union/generic type
Is there a way to avoid including the Listener header?
In the header file of class Book, you should indeed use a forward declaration of MyListener, as the header only defines an std::vector of pointers to MyListener and does not need to know the full declaration of MyListener.
The implementation file of class Book, however, actually needs the full declaration of MyListener, as it calls its update method, so you would include listener.h in the implementation file of class Book instead of in the header file.
Let's suppose the compiler sees the following code:
class Listener;
std::vector<Listener*> pListeners;
// some code...
for(auto& pListener: pListeners) {
pListener->update();
}
Note, how does the compiler see the Listener has a member function update? The symbol update could not be determined until the compiler see the Listener full declaration. Think if you used update with an argument missing, could the compiler capture this problem without seeing the declaration of update? Thus, it cannot translate the code. If you give a full declaration of the Listener, e.g.
class Listener {
public:
Listener() { // some construction
}
void update() {
// dosth
}
};
The compiler could know the update method, its parameters, the return value, etc., and compile it happily.

This declaration has no storage class or type specifier in C++

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

Implementing State Pattern using references

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.

What is the best way to get a callback from an instance of a native C++ class to a C++/CX ref class?

I am writing a C++ WinRT Component DLL for use in my .NET-based WinRT application. The DLL defines a SoundSample ref class that creates an XAudio voice by calling IXAudio2::CreateSourceVoice. CreateSourceVoice takes a "IXAudio2VoiceCallback *pCallback" parameter to enable callbacks on various audio events. Now I am trying to implement that callback based on this article. XAudio will supposedly just call back into methods of my SoundCallback class defined as:
#pragma once
#include "xaudio2.h"
#include "pch.h"
class SoundCallback
: public IXAudio2VoiceCallback
{
private:
//SoundSample^ sample; //does not compile
public:
SoundCallback(void);
~SoundCallback(void);
//Called when the voice has just finished playing a contiguous audio stream.
void OnStreamEnd();
void OnVoiceProcessingPassEnd();
void OnVoiceProcessingPassStart(UINT32 SamplesRequired);
void OnBufferEnd(void * pBufferContext);
void OnBufferStart(void * pBufferContext);
void OnLoopEnd(void * pBufferContext);
void OnVoiceError(void * pBufferContext, HRESULT Error);
};
Everything is fine until I try to figure out how to call back from an instance of my native callback class to the parent SoundSample object. I was thinking I could pass an instance of the SoundSample class to the SoundCallback object, but it seems like it does not allow me to declare a ref class field in the native class:
SoundCallback.h(9): error C2143: syntax error : missing ';' before '^'
SoundCallback.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
SoundCallback.h(9): error C3699: '^' : cannot use this indirection on type 'int'
I looked back at implementing callbacks in native C++ and I could not find a reasonable solution so far. What is the best/easiest way to do this?
Solved it (thanks to Jeremiah Morrill) - the problem is not with any barrier blocking the use of ref classes in basic classes. C4430 means that SoundSample is an unrecognized type, which was hidden by Intellisense - since that seemed to indicate that SoundSample is known.
What needs to be added is a declaration of the SoundSample type and this all starts working fine.
I just added
namespace MyNamespace { ref class SoundSample; }
before the SoundCallback class declaration and then SoundCallback class could declare:
MyNamespace::SoundSample^ sample;