C++ novice here.
I'm trying to teach myself C++ by working on a project to create a Robot that gets commands from and sends telemetry back to a remote server.
I have a TcpCom class on the Robot which contains the socket connection and public functions to send messages and receive messages from the server:
#ifndef TCPCOM_H
#define TCPCOM_H
#define BOOST_DATE_TIME_NO_LIB
#include <boost/asio.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <deque>
#include <mutex>
#include "COM.h"
class TcpCom : public COM
{
public:
TcpCom() : io_srv(), tcpSocket(io_srv), remoteHost(""), remotePort(""), connectedToRemoteHost(false), outboundMsgQueue(), outboundMsgQueueMutex(),
messagesInOutboundMsgQueue(0), incomingMsgQueue(), incomingMsgQueueMutex()
{}
int initialize();
void connectToRemoteHost(const std::string host, const std::string port);
void disconnectFromRemoteHost();
bool messagesWaitingInIncomingMsgQueue();
SoftwareBusMsg getMsgFromIncomingMsgQueue();
void addMsgToOutboundMsgQueue(SoftwareBusMsg& sbMsg);
bool isConnected();
private:
void writeOutboundMsgToSocket();
void deserializeHeader(std::string headerStr, MsgHeader& msgHdr);
void addMessageToIncomingMsgQueue(SoftwareBusMsg& sbMsg);
void readIncomingMsgHeader(MsgHeader& msgHdr);
std::string readIncomingMsgData(uint32_t msgDataLength);
SoftwareBusMsg readMsgFromSocket();
void incomingMsgThread();
void outboundMsgThread();
void startReadAndWriteThreads();
boost::asio::io_service io_srv;
boost::asio::ip::tcp::socket tcpSocket;
std::string remoteHost;
std::string remotePort;
bool connectedToRemoteHost;
std::deque<std::string> outboundMsgQueue;
std::mutex outboundMsgQueueMutex;
boost::interprocess::interprocess_semaphore messagesInOutboundMsgQueue;
std::deque<SoftwareBusMsg> incomingMsgQueue;
std::mutex incomingMsgQueueMutex;
//boost::interprocess::interprocess_semaphore messagesInIncomingMsgQueue;
};
#endif
I want the other classes, such as those responsible for motor control, to have the capability to send messages to the server for telemetry/error reporting. I may be wrong here, but it seems like it would be poor design to directly pass an instance of the TcpCom class to each class that needs the ability to send messages to the server.
Instead, I tried creating a EventReporter class that has a private member that is a reference to the TcpComclass. This would allow the encapsulation of code for handling different types of events (info, errors) and I could pass an initialized 'EventReporter' object to everything that needs it.
#include "TcpCom.hpp"
class EventReporter
{
public:
EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn)
{}
//Will contain call to tcpCom.addMsgToOutboundMsgQueue()
void reportEvent(std::string eventType, std::string message);
private:
TcpCom tcpCom;
};
When I tried compiling this code I got a few errors:
error: use of deleted function 'TcpCom::TcpCom(const TcpCom&)'
error: use of deleted function 'boost::asio::io_service(const boost::asio::io_service&)'
It looks like my new class would be trying to make a copy of TcpCom, which I thought I was avoiding by passing it by reference.
Should I use something like a unique_ptr to avoid copying TcpCom, or is there a better way to make networking functions accessible from other classes?
Thanks!
Kind of tossed up whether to answer this or close as a typo, so I'll post and let the question's Asker tell me.
In
class EventReporter
{
public:
EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn)
{}
//Will contain call to tcpCom.addMsgToOutboundMsgQueue()
void reportEvent(std::string eventType, std::string message);
private:
TcpCom tcpCom; //<- this is not a reference
};
TcpCom tcpCom; defines an instance of TcpCom, not a reference to a TcpCom as the Asker stated they wanted, so tcpCom(tcpComIn) in the member initializer list (Good on them for using the list, by the way. Many C++ programmers who think they are no longer learning don't seem to know they exist) performs the copy They are trying to avoid by passing by reference in the parameter list.
The error messages result from members (std::mutex at the very least. Multiple copies of a mutex would be bad) of TcpCom being uncopyable, so you can't copy one even if you want to.
The simple solution is
class EventReporter
{
public:
EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn)
{}
//Will contain call to tcpCom.addMsgToOutboundMsgQueue()
void reportEvent(std::string eventType, std::string message);
private:
TcpCom & tcpCom; //<- change made here
};
Unless the Asker has other uncopyable objects also being copied else where in their code or the the EventReporter instance can outlive the source TcpCom they should be good to go.
Related
I cam from programming in Java and I thought doing as here [my code] could work the definition of temporal constructors, but I am having problems the proper way of writing the code to just work.
PROBLEM: I want to add a Constructor of the class Coomunication for every port I find in a machine and save it into a vector:
ControlCommunication.cpp:
...
QVector<Comunication *> ports;
...
void ControlCommunication::checkPorts(){
qint16 vendorid = cuquito.getVendorID();
qint16 productid = cuquito.getProductID();
const QString blankString = "N/A";
for (const QSerialPortInfo &serialPortInfo : QSerialPortInfo::availablePorts()) {
Comunication com(serialPortInfo.portName());
addPort(com); // <- I do not know how to get this working well
}
}
ControlCommunication.h:
class ControlCommunication : public QObject
{
Q_OBJECT
public:
explicit ControlCommunication(QObject *parent = nullptr);
QVector<Comunication*> getComunicationPorts(){return comunicationports;}
void addPort(Comunication com);
...
Comunication.h:
#ifndef COMUNICATION_H
#define COMUNICATION_H
#include <QObject>
#include <QSerialPort>
#include <QMainWindow>
class Comunication:public QObject{
Q_OBJECT
public:
Comunication( QString serialPortName);
Comunication();
public:
public slots:
void openSerialPort();
void closeSerialPort();
void writeData(const QByteArray &data);
void readData(QByteArray &data);
void handleError(QSerialPort::SerialPortError error);
QString getPortName(){return portname;};
signals:
private:
QSerialPort *m_serial = nullptr;
QString portname;
};
#endif // COMUNICATION_H
The error I get is: call to implicitly-deleted copy constructor of 'Comunication'
comunication.h:8:20: note: copy constructor of 'Comunication' is implicitly deleted because base class 'QObject' has a deleted copy constructor
qobject.h:449:20: note: 'QObject' has been explicitly marked deleted here
controlcommunication.cpp:27:49: note: passing argument to parameter 'com' here
As I understand from the error message, I cannot call a constructor which is gonna be deleted in that function from other statements. How can i get this working?
The error you're getting mean you can't copy Communication. When you're passing com to addPort, you're making a copy of the object which will be passed to the function. But because you're inheriting a QObject you can't make copies of your objects. Which means you can't those objects by value. You can add pointers or (ideally) a reference to use objects.
But in your case, I don't think that's going to work easily, you seem to want a QVector<Communication*> which I'm assuming will be filled by addPort. But you're creating Communication in your loop which will be delted when it exists the loop, and so pointers to it won't work.
I don't have enough information, and I'm not versed with Qt, so please someone correct if I'm wrong, but I would suggest that you build Communication inside addPort and change QVector<Communication*> to QVector<Communication>.
My intuition would be that Communication doesn't need to inherit from QObject, but I could be wrong. But the data from your program should probably be separated from the Qt stuff, to make things easier to manage.
You are passing the Comunication object by value into the addPort function. This will try to create a copy of the object. But QObjects (and anything derived from QObject) are non-copyable. So you should change your function to take a pointer or reference instead.
Also, you probably need to allocate your objects on the heap because they will go out of scope, freeing any stack memory.
void addPort(Communication *com);
...
for (const QSerialPortInfo &serialPortInfo : QSerialPortInfo::availablePorts()) {
// Allocate on the heap
Comunication *com = new Comunication(serialPortInfo.portName());
// Pass pointer to addPort
addPort(com);
}
First of all, sorry for the title. I didn't know exactly how to give name to the situation I'm facing.
I am developing a project in C++ that will run over QNX (so answers that recur to Windows libraries are not good).
I have one class that holds and manipulates all my data, and a few other classes that are responsible for dealing with my UI.
The UI manipulating classes include my data class, and when they are initialized, they all get a pointer to the same data object (each one uses different parts of it, though). And the normal flow of the program is the UI receiving events from the user, and then making calls to the data class and updating itself, according to the data class replies. That all works just fine.
The problem is, sometimes it might happen that this data class object receives calls from other sorts of external events (let's say a call from a class responsible for communication), asking it to change some of it's values. After doing so, it would have to update the UI (thus, having to make a call to the UI classes).
The actual objects to all the classes (UI and data) are contained by the "main" class. But as the UI classes include the data class to be able to call it's methods, the data class including UI classes in order to be able to call their methods would fall into mutual inclusion.
The problem resumes, in a very simplistic way (I am just trying to give a visual example of the information flow), to something like this:
main.cpp
#include "interface.h"
#include "data.h"
Data data_;
Interface interface_;
// Initialize all data from files, etc
data_.Init();
// Call the interface that will use all of this data
interface_.Init(&data_);
while(1);
interface.h
#include "data.h"
class Interface
{
Data *data_;
void Init(Data *data);
void ReceiveEvent();
void ChangeScreen (int value);
};
interface.cpp
#include "interface.h"
void Interface::Init(Data *data)
{
// Get the pointer locally
data_ = data;
}
// Function called when a (for example) a touch screen input is triggered
void Interface::ReceiveEvent()
{
ChangeScreen(data_->IncreaseParam1());
}
void Interface::ChangeScreen (int value);
{
// Set the value on screen
}
data.h
class Data
{
int param 1;
void Init();
int IncreaseParam1();
void ReceiveExternalEvent();
};
**data.cpp"
#include "data.h"
void Data::Init()
{
// The value actually come from file, but this is enough for my example
param1 = 5;
}
int IncreaseParam1()
{
param1 += 5;
return param1;
}
// This is called from (for example) a communication class that has a
// pointer to the same object that the interface class object has
void ReceiveExternalEvent()
{
IncreaseParam1();
// NOW HERE IT WOULD HAVE TO CALL A METHOD TO UPDATE THE INTERFACE
// WITH THE NEW PARAM1 VALUE!
}
I hope I made myself clear enough.
Can someone please give me ideas on how to deal with this situation?
Thanks a lot in advance!
Both Data and Interface are singletons. You expect to only have one instance of each class in existence. So:
Class Data {
public:
static Data *instance;
Data()
{
instance=this;
}
// Everything else that goes into Data, etc...
};
Class Interface {
public:
static Interface *instance;
Interface()
{
instance=this;
}
// Everything else that goes into Data, etc...
};
Now, ReceiveExternalEvent() will simply invoke Data::instance->method() and/or Interface::instance->method(), and so on...
This is a classical singleton design pattern.
Also, you might find some additional Google food of likely interest to you: "model view controller" and "mvc".
I have a library that is all tested thoroughly through google test suite. I am trying to keep it "pimpl" clean, but I'm running into a segfault I can't quite figure out.
Relevant Code:
Interface.h:
class Interface{
public:
Interface();
void Function(const int argument);
private:
std::unique_ptr<Implementation> Implement;
std::unique_ptr<DependencyInjection> Injection1, Injection2;
};
Interface.cpp:
Interface::Interface()
: Injection1(new DependencyInjection()),
Injection2(new DependencyInjection()),
Implement(new Implementation(*Injection1, *Injection2)) {}
void Interface::Function(const int argument){ Implement->Function(argument); }
Implementation.h:
class Implementation{
public:
Implementation(AbstractInjection &injection1, AbstractInjection &injection2);
void Function(const int argument);
private:
AbstractInjection Injection1, Injection2;
};
Implementation.cpp
Implementation::Implementation(AbstractInjection &injection1, AbstractInjection &injection2)
: Injection1(injection1),
Injection2(injection2) {}
void Implementation::Function(const int argument){
injection1.Function(argument); } // code from here out is all well tested and works
So when I create the interface and call Interface.Function() the code segfaults when it tries to evaluate Implementation.Function(). I've ran gdb through everything I can think of, all the pointers are non-null.
If I just create a test that looks like
std::unique_ptr<DependencyInjection1> injection1(new DependencyInjection());
std::unique_ptr<DependencyInjection2> injection2(new DependencyInjection());
std::unique_ptr<Implementation> implement(new Implementation(*injection1, *injection2));
implement->Function(0);
The code works fine and does not segfault
But if I create a test like
Interface iface;
iface.Function(0);
it will segfault.
I am new to the whole unique_ptr thing, but I have a suspicion that isn't the larger problem. It may be a red herring, I don't know.
The problem should actually pop as as a warning.
Initializers are done in the order in which they appear in the class definition, not in which they appear in the constructor!
Switch it to:
class Interface{
public:
Interface();
void Function(const int argument);
private:
std::unique_ptr<DependencyInjection> Injection1, Injection2;
std::unique_ptr<Implementation> Implement;
};
From here: C++: Initialization Order of Class Data Members, this is "12.6.2 of the C++ Standard"
You've got a wrong order of member fields, they are initialized in order they are declared in the class. So implement is initialized before both injections. Use -Werror=reorder to get compiler error (for GCC and probably CLang)
The qml viewer (for 4.8 and 5.0) is implemented like that:
In the .h(eader) we have:
class QtQuick2ApplicationViewer : public QQuickView
{
Q_OBJECT
...
private:
class QtQuick2ApplicationViewerPrivate *d;
};
Then in the .CPP file:
class QtQuick2ApplicationViewerPrivate
{
QString mainQmlFile;
friend class QtQuick2ApplicationViewer;
static QString adjustPath(const QString &path);
};
QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent)
: QQuickView(parent)
, d(new QtQuick2ApplicationViewerPrivate())
{
connect(engine(), SIGNAL(quit()), SLOT(close()));
setResizeMode(QQuickView::SizeRootObjectToView);
#ifdef Q_OS_ANDROID
engine()->setBaseUrl(QUrl::fromLocalFile("/"));
#endif
}
Why is using friend necessary here? I don't see any reason why would anybody use a friend class. Is there any real use for friend classes (except for exotics that anybody could live without)?
.h
#include
class QtQuick2ApplicationViewer : public QQuickView
{
Q_OBJECT
public:
explicit QtQuick2ApplicationViewer(QWindow *parent = 0);
virtual ~QtQuick2ApplicationViewer();
void setMainQmlFile(const QString &file);
void addImportPath(const QString &path);
void showExpanded();
private:
class QtQuick2ApplicationViewerPrivate *d;
};
.cpp
#include "qtquick2applicationviewer.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtQml/QQmlEngine>
class QtQuick2ApplicationViewerPrivate
{
QString mainQmlFile;
friend class QtQuick2ApplicationViewer;
static QString adjustPath(const QString &path);
};
QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path)
{
#ifdef Q_OS_UNIX
#ifdef Q_OS_MAC
if (!QDir::isAbsolutePath(path))
return QString::fromLatin1("%1/../Resources/%2")
.arg(QCoreApplication::applicationDirPath(), path);
#elif !defined(Q_OS_ANDROID)
const QString pathInInstallDir =
QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
if (QFileInfo(pathInInstallDir).exists())
return pathInInstallDir;
#endif
#endif
return path;
}
QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent)
: QQuickView(parent)
, d(new QtQuick2ApplicationViewerPrivate())
{
connect(engine(), SIGNAL(quit()), SLOT(close()));
setResizeMode(QQuickView::SizeRootObjectToView);
#ifdef Q_OS_ANDROID
engine()->setBaseUrl(QUrl::fromLocalFile("/"));
#endif
}
QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer()
{
delete d;
}
void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file)
{
d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file);
setSource(QUrl::fromLocalFile(d->mainQmlFile));
}
void QtQuick2ApplicationViewer::addImportPath(const QString &path)
{
engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path));
}
void QtQuick2ApplicationViewer::showExpanded()
{
#if defined(Q_WS_SIMULATOR)
showFullScreen();
#else
show();
#endif
}
Friends examine friends' privates. You sure can do without access restrictions at all, but once you use it, being friendly helps in intimate situations.
class Me;
class You {
friend class Me;
private:
Home _home;
Car _car;
public:
void bar(Me my);
};
class Me {
Stuff _stuff;
public:
foo(You you) {
//If you consider me a friend
you._home.enter(); //I can enter your `private _home`
you._car.drive(); //I can drive your `private _car`.
}
};
void You::bar(Me my) {
my.stuff //this is an error because I don't consider you a friend so you can't touch my `private _stuff`.
}
Knowing you can always count on me, for sure. That's what friends are for. http://www.youtube.com/watch?v=xGbnua2kSa8
But I guess you're asking about friend classes in C++.
The whole point of "scope" is to define exactly who can see what in another class. You don't "need friends" any more than you need "protected" or "private", in the sense that you could make everything in all your classes public, and your program would successfullly compile and run. But the idea is to establish -- and document -- exactly what is the public interface of a class, and thus cannot be changed without considering the impact on other classes, and what is an internal implementation, which can be freely re-worked or re-organized without fear of impacting other classes.
So the point of a "friend" is to say: Hey, I have this class X, and this other class Y. And in general other classes don't need to know how X goes about doing it's job. But Y interacts with some low-level thing in X, so it needs to see it. Thus I make Y a friend of X. Like, I have an Investor class that has a function that (presumably among other things) has a function to calculate the total amount of a customer's investments. In general, other classes shouldn't care how I do that calculation: they just want the total. But now I have a TaxReporting class that needs to know how much of that balance is in taxable securities and how much is in non-taxable securities. Maybe I don't want to make these functions public because the information is confidential and I want to limit access for real-world privacy reasons. More often, I don't want to make it public because the calculation is tricky or subject to frequent change, and I want to keep tight control on what classes access it to limit the problems caused when things change. So I make TaxReporting a friend so it can access some functions that make the distinction, without opening these to the world.
In practice, when I was doing C++ I rarely used friends. But "rarely" is not "never". If you find yourself saying, "Oh, I have to make this public just so this one other class can see it", then maybe instead of making it public you should make a friend.
"friend" is super useful and something you want to use all the time.
Typical use cases are:
You have a class that uses subclasses where the subclass is allowed to use private functions of the class that owns the subclasses:
class ManagedObject
{
public:
void doStuff() { mMgr->updateManager(); }
private:
Manager* mMgr;
};
class Manager
{
friend ManagedObject;
public:
ManagedObject* createManagedObject();
private:
void updateManager() { }
};
So in this case you have a class that creates and deals with "managedObject". Whenever this object is manipulated it needs to update the object that created it. You want users of your class to know that they don't ever need to call "updateManager" and in fact wat to generate a compile time error if they do.
Another common case is when you have a function which acts like a class member but cannot for some reason be a class member. An example is operator<<. If you write your own io stream class, or if you want to create a serialization system that users operator<<:
class serializedObject
{
public:
friend Serializer& operator<< ( Serializer& s, const serializedObject& obj );
protected:
u32 mSecretMember;
};
Serializer& operator<<( Serializer& s, serializedObject& obj )
{
serializer << obj.mSecretMember;
return s;
}
In this case the serialization function cannot be a member of serializedObject, but needs to look at the internals of serializedObject to serialize it. You will see similar patterns of you create other operators ( like addition ) where the RHS of the operator is not the same class as the LHS
In Qt, there is something called a 'guarantee of binary compatibility', which means that your app can run against Qt4.8, 4.8.1, and 4.8.2 and so forth without recompiling.
In order to achieve this the vtable for objects cannot change. So, Qt classes are written using the "PIMPL" (pointer to implementation) idiom.
The "Private" class is the PRIVATE implementation of the public class - it is an implementation detail of QtQuick2ApplicationViewer. No one in the whole world knows about the private class except the public class. These two classes are deeply intertwined by design. In fact, they are really different aspects of a single object that has been partitioned c++ wise in order to achieve the binary compatibility guarantee.
It is reasonable in this context that the private class can access the public class.
2) In this context quit is not QApplication::quit(), that is slot of cause, but some internal signal of engine().
I am trying to implement a very clean Command Pattern in a library.
I have the following structure right now (a few parts are still being finished up):
users (client-code) have some Object, call it "Manager"
Manager holds a collection of shared_ptr<Foo>
Manager provides access to the collection by returning shared_ptr<Foo>
I have a Command abstract class and a hierarchy of commands for actions to perform on Foo
Client code should not call Command::execute(), only Manager should, Manager::execute(shared_ptr<Command>), so that it can handle undo/redo
I would like to follow the following rules:
users (client-code) have some Object, call it "Manager"
Manager holds a collection of shared_ptr<Foo>
Manager provides access to the collection by returning shared_ptr<const Foo>
I have a Command abstract class and a hierarchy of commands for actions to perform on Foo
Client code cannot (without workarounds) call Command::execute(), only Manager can, Manager::execute(shared_ptr<Command>), so that it can handle undo/redo and get non-const smart pointers
A Manager must be able to allow Command objects to access and modify shared_ptr<Foo> even though the user initializes Command objecst with shared_ptr<const Foo>
I am just trying to figure out the best way to handle giving out shared_ptr<const Foo> while allowing number 5 and 6 to work.
Is there any example/design pattern that does this which I could learn from? Is this a good idea compared to what I already have/am working on?
I think this passkey pattern should be the right thing for you:
class CommandExecuteKey{
private:
friend class Manager;
CommandExecuteKey(){}
};
class Command{
public:
// usual stuff
void execute(CommandExecuteKey);
};
class Manager{
public
void execute(Command& cmd){
// do whatever you need to do
cmd.execute(CommandExecuteKey());
}
};
Now, Command doesn't know anything about Manager, only about the key that is needed for the execute function. The user won't be able to call the execute method directly, as only Manager can create CommandExecuteKey objects, thanks to a private constructor and friendship.
int main(){
Command cmd;
Manager mgr;
//cmd.execute(CommandExecuteKey()); // error: constructor not accessible
mgr.execute(cmd); // works fine, Manager can create a key
}
Now, for your 6th point:
When you get the command in, search all your shared_ptr<Foo>s for the correct object (using the saved shared_ptr of the command as a search-key) and then pass that mutable one from your internal shared_ptrs back to the command.
Since it wouldn't make any sense to me otherwise, I'm going to assume that
your library provides the Manager class (or at least a base class), and
clients have to use that class to invoke a Command.
In that case, maybe something like this could work:
void Manager::execute(Command& cmd, shared_ptr<Foo const> const& target)
{
shared_ptr<Foo> mutableTarget = this->LookupMutableFoo(mutableTarget); // throws if not found
cmd.execute(mutableTarget); // client cannot invoke without mutable pointer
}
// or, if the "target" needs to be stored in the Command you could use something like this:
void Manager::execute(Command& cmd)
{
shared_ptr<Foo> mutableTarget = this->LookupMutableFoo(cmd.GetTarget()); // throws if not found
cmd.execute(mutableTarget); // client cannot invoke without mutable pointer
}
I'm not sure though if using const is the best solution here. Maybe you should wrap your Foo objects in e.g. ClientFoo objects. The manager only hands out pointers to ClientFoo. The manager can then (e.g. via friend) get the Foo from the ClientFoo, and use it to invoke the Command.
I'm not following your question 100%, but here goes...
The only thing I can think of for #5 is to make Command::execute private/protected and make Manager a friend of Command. The downside of this approach is that you've now introduced a dependency from Command to Manager.
As for #6, if the user's shared_ptr<const Foo> objects were originated from Manager's shared_ptr<Foo> collection, then Manager should be able to safely const_pointer_cast shared_ptr<const Foo*> back into shared_ptr<Foo*>. If Manager attempts to const cast a shared_ptr<const Foo*>, where the pointee is an actual constant object, you'll get undefined behavior.
I've thought of another solution for #5:
Define an ExecutableCommand class, derived from Command. ExecutableCommand has an added method to invoke the command, to be used only by Manager. Clients can only access ExecutableCommand objects via pointers/references to Command. When a Manager wants to invoke a Command, it downcasts it to a ExecutableCommand to gain access to the invocation interface.
Working example (including const_pointer_cast for #6):
#include <iostream>
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost;
//------------------------------------------------------------------------------
struct Foo
{
Foo(int x) : x(x) {}
void print() {++x; cout << "x = " << x << "\n";} // non-const
int x;
};
//------------------------------------------------------------------------------
struct Command
{
// Interface accessible to users
std::string name;
private:
virtual void execute() = 0;
};
//------------------------------------------------------------------------------
struct ExecutableCommand : public Command
{
// Only accessible to Manager
virtual void execute() {} // You may want to make this pure virtual
};
//------------------------------------------------------------------------------
struct PrintCommand : public ExecutableCommand
{
PrintCommand(shared_ptr<const Foo> foo)
: foo_( const_pointer_cast<Foo>(foo) ) {}
void execute() {foo_->print();}
private:
shared_ptr<Foo> foo_;
};
//------------------------------------------------------------------------------
struct Manager
{
void execute(Command& command)
{
ExecutableCommand& ecmd = dynamic_cast<ExecutableCommand&>(command);
ecmd.execute();
}
void addFoo(shared_ptr<Foo> foo) {fooVec.push_back(foo);}
shared_ptr<const Foo> getFoo(size_t index) {return fooVec.at(index);}
private:
std::vector< shared_ptr<Foo> > fooVec;
};
//------------------------------------------------------------------------------
int main()
{
Manager mgr;
mgr.addFoo( shared_ptr<Foo>(new Foo(41)) );
Command* print = new PrintCommand(mgr.getFoo(0));
// print.execute() // Not allowed
mgr.execute(*print);
delete print;
}