C++ private access to other classes' members - c++

I'm writing a multi-threaded server using boost::asio (for sockets), boost::thread (for threading), libconfig++ (for configuration files reading) and protocol buffers (for the protocol implementation).
The server follows more or less this route: main() -> creates an Application object -> runs application object. Application loads configuration file, then creates the server object (which is passed the configuration class as a const). Server object configures itself and binds the port, starts accepting, blah. Whenever a new client is detected, the server creates a new Client object, and then creates a thread running the client's connection handler.
All of this is to explain that the configuration file is loaded from my Application class, and then passed all the way down to my Client class. This shouldn't pose any kind of trouble if the libconfig object was passed directly all the way to the Client, yet as we all know, multi-threading implies that memory corrupts when accessed simultaneously by two or more threads.
The way to solve this was discussed in other post and ended up with the implementation of a wrapper which automagically solves the mutex problem.
The magical class
app_config.h
#ifndef _APP_CONFIG_H_
#define _APP_CONFIG_H_ 1
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/noncopyable.hpp>
#include <libconfig.h++>
#include <string>
namespace BBCP {
namespace App {
class ConfigLock;
class Config {
public:
friend class BBCP::App::ConfigLock;
Config(std::string const &file) :
cfg(new libconfig::Config()),
mutex(new boost::mutex())
{
cfg->readFile(file.c_str());
}
private:
boost::shared_ptr<libconfig::Config> cfg;
boost::shared_ptr<boost::mutex> mutex;
};
class Server;
class Client;
class ConfigLock : boost::noncopyable {
public:
ConfigLock(BBCP::App::Config const &wrapper) :
cfg(wrapper.cfg),
mutex(wrapper.mutex),
lock(new LockType(*mutex))
{ }
libconfig::Config &get() throw() { return *cfg; };
private:
boost::shared_ptr<libconfig::Config> cfg;
boost::shared_ptr<boost::mutex> mutex;
typedef boost::lock_guard<boost::mutex> LockType;
boost::shared_ptr<LockType> lock;
};
}
}
#endif
For lazy people, this class consists of... well, two classes (irony?): BBCP::App::Config and BBCP::App::ConfigLock. BBCP::App::Config simply loads a file, while BBCP::App::ConfigLock takes a BBCP::App::Config as an argument, and then locks BBCP::App::Config's mutex. Once the lock has been created, one calls BBCP::App::ConfigLock::get, which returns a reference to the libconfig::Config object!.
THE problem
Well:
server.cpp:
void BBCP::App::Server::startAccept() {
newClient.reset(new BBCP::App::Client(io_service, config_wrapper));
acceptor.async_accept(newClient->getSocket(), boost::bind(&BBCP::App::Server::acceptHandler, this, boost::asio::placeholders::error));
}
This function creates a new client object, loaded with the boost::asio::io_service object and BBCP::App::Config object.
server.cpp
void BBCP::App::Server::acceptHandler(boost::system::error_code const &e) {
if (!acceptor.is_open()) {
// ARR ERROR!
return;
}
if (!e) {
client_pool.create_thread(*newClient);
}
else {
// HANDLE ME ERROR
throw;
}
startAccept();
}
This function creates a new thread or (not implemented yet) errors in case of... well, errors, then starts the accept loop again.
Client code mostly doesn't matter until this part:
client.cpp:
void BBCP::App::Client::parseBody() {
BBCP::Protocol::Header header;
BBCP::Protocol::Hello hello;
boost::scoped_ptr<BBCP::App::ConfigLock> lock;
libconfig::Config *cfg;
(...)
switch ((enum BBCP::Protocol::PacketType)header.type()) {
case BBCP::Protocol::HELLO:
(...)
// config_wrapper is a private variable in the client class!
lock.reset(new BBCP::App::ConfigLock(config_wrapper));
// ARRRRRRR HERE BE DRAGOONS!!
*cfg = lock->get();
(...)
lock.reset();
break;
(...)
}
(...)
}
Well, truth be told, I didn't expect this kind of error:
/usr/include/libconfig.h++: In member function ‘void BBCP::App::Client::parseBody()’:
/usr/include/libconfig.h++:338:13: error: ‘libconfig::Config& libconfig::Config::operator=(const libconfig::Config&)’ is private
client.cpp:64:30: error: within this context
client.cpp:71:21: error: request for member ‘exists’ in ‘cfg’, which is of non-class type ‘libconfig::Config*’
client.cpp:77:51: error: request for member ‘lookup’ in ‘cfg’, which is of non-class type ‘libconfig::Config*’
But here it is, and I need some way to solve it :(. I've tried making BBCP::App::Client a friend class of BBCP::App::ConfigLock, but then it went like:
In file included from ../include/app_config.h:4:0,
from ../include/app_main.h:6,
from main.cpp:18:
../include/app_client.h:15:53: error: ‘BBCP::App::Config’ has not been declared
In file included from ../include/app_config.h:4:0,
from ../include/app_main.h:6,
from main.cpp:18:
../include/app_client.h:32:5: error: ‘Config’ in namespace ‘BBCP::App’ does not name a type
In file included from ../include/app_config.h:4:0,
from ../include/app_main.h:6,
from main.cpp:18:
../include/app_client.h: In constructor ‘BBCP::App::Client::Client(boost::asio::io_service&, const int&)’:
../include/app_client.h:15:120: error: class ‘BBCP::App::Client’ does not have any field named ‘config_wrapper’
And then I went like O_O, so I just gave up and came here, once again looking for some über C++ guru hackz0r's help and scolding for doing such a misdeed as trying to access another class's private members is.

The first thing is figuring out if you are going in the right direction, and the next step is getting there.
Why is the assignment operator of the Config type private? By default the compiler generated assignment operator is public, so if it has been declared as private, chances are that there is a reason for the object not to be copied, or else you should make it public and the problem would no longer be a problem.
As of your particular problem after adding the friend declaration, it seems to indicate that you have missed including the header where the Config type is declared/defined. And then there are some more errors in the code (a member that has not been defined - result of the previous error?), or in the original code trying to access the object referred by a pointer without dereferencing it...

You probably wanted to store a pointer to the config object in cfg instead of creating a copy (and dereferencing an uninitialized pointer):
cfg = &local->get();

Related

C++ composition without using the heap in embedded systems

I'm fairly new to C++, this is also my first post on here. I'm trying to use C++ in an embedded systems project so I can take the OOP approach. I'm using the AVR crosspack toolchain (AVR G++ compiler)
My problem is this:
From what i've read, the heap should not be used for dynamic memory allocation in embedded systems. In any case, there is no implementation for "new" in AVR G++ anyway. I'm using composition, starting with a USART driver (lets call it a service), and a logger (singleton pattern, and also a service).
It's my understanding that services should have their dependancies passed in on instantiation using constructor parameters, however when I try to compose the objects needed in this way I get the following error:
Main/main.cpp: In function 'int main()':
Main/main.cpp:21:13: error: request for member 'log' in 'logSystem', which is of non-class type 'LogSystem(Usart)'
21 | logSystem.log("Hello");
| ^~~
make: *** [Main/main.o] Error 1
My sense is that my syntax for passing in an object as a constructor parameter is wrong, but I'm not sure what it should be as all the examples i can find use the "new" keyword in the constructor definition to create the object on the free store. Can anyone help?
The Code:
In "usart.h":
#include <avr/io.h>
#include <util/setbaud.h>
class Usart
{
public:
// Constructor and destructor
Usart();
~Usart();
// Initialisation routine
static void const init(void);
// Utility function to transmit a string
static void const print(const char myString[]);
};
In "logger.h":
#include "usart.h"
class LogSystem
{
public:
LogSystem(Usart usart);
~LogSystem();
Usart usart;
static void const log(char *msg);
};
In "logger.cpp"
#include "logger.h"
LogSystem::LogSystem(Usart usart)
{
Usart usart;
usart.init();
}
LogSystem::~LogSystem()
{
}
LogSystem::log(char *msg)
{
usart.print(msg);
}
In "main.cpp":
#include "logger.h"
int main()
{
LogSystem logSystem(Usart usart);
while(1)
{
logSystem.log("Hello");
}
return 0;
}
[...] the heap should not be used for dynamic memory allocation in embedded systems.
It depends. I'm currently in an embedded project with maximum safety-related requirements, and we use new, but not delete. So we have a heap, but don't allocate "dynamically", because all allocated objects are kept during the runtime.
In any case, there is no implementation for "new" in AVR G++ anyway.
Is this true? I never checked... It might be necessary to provide a heap before being able to use new.
It's my understanding that services should have their dependancies passed in on instantiation using constructor parameters, [...]
This is a good idea. ;-) It helps unit-testing.
For your syntactical and design problems: This is how I would write your sources.
"usart.h":
All methods are non-static to have access to member variables.
The const attribute on a return type is doing nothing. Did you mean to declare the method constant? Then const belongs after the parameter list. However, this attribute might be wrong if such a method changes any member variable.
#include <avr/io.h>
#include <util/setbaud.h>
class Usart
{
public:
Usart();
~Usart();
void init(void);
void print(const char myString[]);
};
"logger.h":
Just give and store a reference to the USART to avoid a copy.
#include "usart.h"
class LogSystem
{
public:
LogSystem(Usart& usart);
~LogSystem();
void log(const char *msg);
private:
Usart& _usart;
};
"logger.cpp"
The member variable _usart is directly initialized in the constructor, before any statement is executed.
#include "logger.h"
LogSystem::LogSystem(Usart& usart) : _usart(usart)
{
_usart.init();
}
LogSystem::~LogSystem()
{
}
void LogSystem::log(const char *msg)
{
_usart.print(msg);
}
"main.cpp":
Provide the USART object on the stack, as the logger.
#include "logger.h"
int main()
{
Usart usart;
LogSystem logSystem(usart);
while(1)
{
logSystem.log("Hello");
}
return 0;
}
The singleton design pattern is deprecated since it was invented, because it is so hard to test. Simply use just one object or a limiting object factory.

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.

Hiding library internal class to clients C++: use friend?

I'm trying to develop a networking part in my basic game engine in C++, but I'm faced with a rather strange problem (it is for me).
I got a Singleton Networker class that handles the set-up of a socket (UDP) and will try to register the username the client provided to the server, returning a bool that represents if the username is already taken by a different player or not. The class itself does not handle the packets itself, I aim to use a Packethandler class for that.
The problem is that I don't want a client to be able to create a PacketHandler directly because the entire point of the Networker class is to provide some kind of interface for handling that. The first idea I had is 'make the constructor of Packethandler private and create a Singleton' but then ofcourse the client can still ask the instance. Then I quickly though 'well protected then' but Networker is not extending PacketHandler. Then I thought 'well let's make Networker a friend of PacketHandler'. All the info I found up till now seems to discourage Friend usage however, so I wonder:
Is my plan for the simple networking part flawed thus facing me with an issue like this or is my problem the reason friend functionality exists in the first place? What is the take of you guys on this, do you have a much better idea?
Edit: code of my idea.
Packethandler.h
#ifndef FANCY_PACKET_HANDLER
#define FANCY_PACKET_HANDLER
#include <SFML/Network.hpp>
namespace fancy {
namespace network {
class PacketHandler
{
friend class Networker;
private:
sf::IpAddress _hostAddress;
sf::UdpSocket _socket;
PacketHandler(std::string hostAdress);
public:
~PacketHandler();
void sendPacket(const char* packet_data, const unsigned int packet_size);
char* receivePacket();
};
}
}
#endif
Networker.h
#ifndef FANCY_NETWORKER
#define FANCY_NETWORKER
#include <SFML/Network.hpp>
#include <Engine/PacketHandler.h>
namespace fancy {
namespace network {
class Networker
{
public:
static Networker* instance();
bool openUdpSocket(unsigned short port);
bool registerUsername(char* username);
char* receiveOnSocket();
protected:
Networker();
private:
static Networker* _instance;
static PacketHandler* _packetHandler;
const char* _username;
sf::IpAddress _hostAddress;
sf::UdpSocket _socket;
};
}
}
#endif
If you wish to provide an interface and hide all the implementation details, you'd better define a pure virtual class (e.g. Networker) which is visible to a user (say in .h-file), and write an implementation in a descendant class (e.g. NetworkerImpl) which is NOT visible to a user. You can then declare in the header file a function (or even a static method of the Networker class) like Networker *CreateNetworker(); (so the declaration is visible to a user), and then implement the function in .cc file along with your NetworkerImpl (so that the implementation is not visible to a user) like return new NetworkerImpl();.

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.

Dealing with circular includes in the context of circular references

As a follow up to an older question of mine, I wish to implement a client-server mockup simulation, where the client initiates a sequence of actions that involve calling methods on the server, which, in turn, can call methods on the client (let's ignore the issue that the stack may blow up).
More specifically, since I want to split the implementation from the definition, I will have server.h and server.cpp for the Server class and client.h and client.cpp for the Client class. Since Server holds a reference to Client and calls methods from it, it needs to #include "client.h". Also, Client holds a reference to Server and calls methods from it, it needs to #include "server.h". At this point, even if I use header guards in both server.h and client.h, it still messes up (yeah, it's expected) so I decided to forward-declare the Server class in client.h and the Client class in server.h. Unfortunately, this is not enough to solve the issue, because I'm also calling methods from the two classes, so I managed to make it compile & run (properly, as far as I can tell), by including server.h in client.cpp and client.h in server.cpp.
Does the above "hack" sound reasonable? Should I expect some unforeseen consequences? Is there any "smarter" way to do this without having to implement a proxy class?
Here's a rudimentary sample of how the implementation will look like:
file client.h:
#ifndef CLIENT_H
#define CLIENT_H
#include <iostream>
#include <memory>
class Server;
class Client
{
private:
std::shared_ptr<const Server> server;
public:
Client () {}
void setServer (const std::shared_ptr<const Server> &server);
void doStuff () const;
void doOtherStuff () const;
};
#endif
file client.cpp:
#include "client.h"
#include "server.h"
void Client::setServer (const std::shared_ptr<const Server> &server)
{
this->server = server;
}
void Client::doStuff () const
{
this->server->doStuff();
}
void Client::doOtherStuff () const
{
std::cout << "All done!" << std::endl;
}
file server.h:
#ifndef SERVER_H
#define SERVER_H
#include <iostream>
#include <memory>
class Client;
class Server
{
private:
std::weak_ptr<const Client> client;
public:
Server () {}
void setClient (const std::weak_ptr<const Client> &client);
void doStuff () const;
};
#endif
file sever.cpp:
#include "server.h"
#include "client.h"
void Server::setClient (const std::weak_ptr<const Client> &client)
{
this->client = client;
}
void Server::doStuff () const
{
this->client.lock()->doOtherStuff();
}
file main.cpp:
#include <iostream>
#include <memory>
#include "client.h"
#include "server.h"
int main ()
{
std::shared_ptr<Client> client(new Client);
std::shared_ptr<Server> server(new Server);
client->setServer(server);
server->setClient(client);
client->doStuff();
return 0;
}
That looks good to me. Forward declaring server in the client.h and forward declaring client in the server.h is the right thing to do.
It is perfectly fine to then include both header files in the .c or .cpp file - all you need to avoid is including the header files in a circle.
The "Hack" is none, it's perfectly common practice to separate declaration and implementation of the two classes as you did. And it's perfectly normal that the *.cpp include both Headers.
Sidenote: First consider different signatures for your setServer and setClient methods: In both methods, you copy the argument. Both copies are nontrivial, since the use_counts and/or weak_count have to be updated. If the argument indeed is an existing argument, that is ok, but if it is a temporary, the copy will increase the count and destruction of the temporary will decrease it again, each time an internal pointer has to be dereferenced. In contrast, moving a shared_ptr or weak_ptr does not affect the use counts but resets the temporary. Destruction of that reset temporary again does not affect the use count (it effectively is a null pointer).
Secondly, always prefer make_shared over simple new, because it saves you one allocation. So use this implementation instead:
void Client::setServer (std::shared_ptr<const Server> server)
{
this->server = std::move(server);
}
int main ()
{
auto client = std::make_shared<Client>(); //prefer make_shared
auto server = std::make_shared<Server>();
/* 1 */
client->setServer(server); //by copy, if you need to continue to use server
/* 2 */
server->setClient(std::move(client)); //by moving
}
Call 1 will be as expensive at it was, you make one copy pf the shared_ptr, only this time you make it while passing the argument, not inside the method. Call 2 will be cheaper, because the shared_ptr is moved around and never copied.
My following statement is false (see comments) and applies only to unique_ptr, not to shared_ptr:
But: Since you use a std::shared_ptr<const Server> in Client, you
will have to define Client's destructor inside client.cpp. The
reason is that if you don't, the compiler will generate it for you,
calling the shared_ptr's and thus Server's destructor which has
not been declared inside client.h. At reasonably high warning levels
you compiler should complain about calling delete on a an undefined
class' pointer.
Does the above "hack" sound reasonable? Should I expect some
unforeseen consequences? Is there any "smarter" way to do this without
having to implement a proxy class?
Forward declaration and use include directive to is the normal and right way to break circular include.