I have many interfaces for different listeners, the all look like this:
class ListenerA
{
public:
virtual void
onEventA(const EventA&) = 0;
};
class ListenerB
{
public:
virtual void
onEventB(const EventB&) = 0;
};
When testing, I always end up just collecting those events in a std::vector for analyzing them afterwards in a specific test suite. Those event collectors all look the same like this one for example:
class EventACollector : public ListenerA
{
public:
const auto&
events() const
{
return m_events;
}
private:
void
onEventA(const EventA& event) override
{
m_events.emplace_back(event);
}
std::vector<EventA> m_events;
};
Is there a way to template an EventTCollector, so that I do not have to write it every time? Given that the virtual function name does change for every listeners?
C++ does not have introspection, so you cannot find the virtual function in ListenerA. The other parts can go in a templated base class, but the override you'll need to define manually.
Modern C++ would use a std::function<void(EventA)> instead of a named interface, but that won't help you as a user of that old interface.
I'm working on a UI framework and trying to make my code more manageable and using interfaces(I know they're just classes.) seems to be the best option.
I'll give you an example of what i want to do:
In the Control base class it will have the general members that all controls will have such as ID,name and location. I want to be able to implement an interface that will manage the text of say a button. The interface will store and draw the text.
Now to do this i will need to override the Draw() function however i don't know how i forward declare that.
Psudo code
class ITextAble
virtual void DrawText() override Control::Draw()
{
Control::Draw();
GetRenderWindow()->draw(m_text);
}
class Button : public ITextAble
virtual void Draw ()
{
m_renderWindow->draw(m_shape);
}
sf::RenderWindow * GetRenderWindow () const
{
return m_renderWindow;
}
If you can't tell already I'm pretty new to C++ programming, i have no idea if this is even possible to do in C++ but if true I'm going to be amazed yet again.
You'd better use some ready lib like fltk, wxWidgets, QT, MFC, GTKMM etc.
You will find creating a GUI lib a super complex task.
Looks like you don't understand the interface (pure virtual class) concept. Such a class must not have any members - only pure virtual methods. Otherwise - this is an abstract class.
Read Scott Meyers: Effective C++
Something which can cover your concept using classic dynamic polymorphism version:
WARN! THIS IS BAD DESIGN !!!
Better way - is without sf::RenderWindow * GetRenderWindow () const function at all.
// a pure virtual class - interface
class IControl {
IControl(const IControl&) = delete;
IControl& operator=(const IControl&) = delete;
protected:
constexpr IControl() noexcept
{}
protected:
virtual sf::RenderWindow * GetRenderWindow() const = 0;
public:
virtual ~IControl() noexcept
{}
}
// an abstract class
class ITextAble:public IControl {
ITextAble(const ITextAble&) = delete;
ITextAble& operator=(const ITextAble&) = delete;
protected:
ITextAble(const std::string& caption):
IControl(),
caption_(caption)
{}
void DrawText();
public:
virtual ~ITextAble() noexcept = 0;
private:
std::string caption_;
};
// in .cpp file
void ITextAble::DrawText()
{
this->GetRenderWindow()->draw(caption_.data());
}
ITextAble::~ITextAble() noexcept
{}
//
class Button :public ITextAble
{
public:
Button(int w, int h, const char* caption) :
ITextAble(caption),
window_(new sf::RenderWindow(w,h) ),
{}
void show() {
this->DrawText();
}
virtual ~Button() noexecept override
{}
protected:
virtual sf::RenderWindow* GetRenderWindow() const override {
return window_;
}
private:
sf::RenderWindow* window_;
};
// pointer on reference
Button *btn = new Button(120, 60, "Click me");
btn->show();
I am writing an application that can launch new process'. I have identified that these process' will fundamentally differ in two ways, either they can run standalone or depend on an existing process to function. So I therefore have created two abstract classes, inheriting from a base abstract class.
I am trying to work out how to write a factory or other design pattern that will return the class I need depending on a file extension string I give, which will happen at runtime. However I don't think that the factory pattern is a good,sensible fit as these fundamental difference results in differing constructors. I could write myself a huge switch or nested if statement that would work, but for this project I am really trying to increase my c++ knowledge (this is the first time I have used inheritance really).
Say I have my abstract base class :
class launchable {
protected:
std::string name;
std::string directory;
std::string path;
std::string fileType;
std::vector<std::string> launchArgs;
bool hasLaunched;
launchable(std::string _name, std::string _directory,std::string _fileType,std::vector<std::string> _args);
public:
virtual void start() = 0;
virtual void stop() = 0;
virtual void writeMessage(std::string theMessage) = 0;
virtual boost::optional<std::string> readMessage() = 0;
};
and then two further abstract classes inheriting from this, firstly a standalone class that starts/stops and writes to its own process:
class standalone : public launchable{
protected:
processManager *manager;
std::shared_ptr<processManager::launchableProcess> process;
virtual std::string formatWriteMessage(std::string theMessage) = 0;
standalone(std::string _name, std::string _directory,std::string _fileType,std::vector<std::string> _args,processManager *_manager);
public:
virtual void start() = 0;
virtual void stop() = 0;
void writeMessage(std::string theMessage);
boost::optional<std::string> readMessage();
};
and a dependent class that must start/stop/read/write through a standalone process:
class dependent : public launchable{
protected:
standalone *dependency;
dependent(std::string _name, std::string _directory,std::string _type,std::vector<std::string> _args,standalone *_dependency);
public:
virtual void start() = 0;
virtual void stop() = 0;
void writeMessage(std::string theMessage);
boost::optional<std::string> readMessage();
};
An example concrete standalone, *nix executable that runs on a command line:
class executable : public standalone {
private:
std::string formatWriteMessage(std::string theMessage);
public:
using standalone::standalone;
void start();
void stop();
};
And example concrete dependable, a supercollider patch that must run through a *nix command line interpreter:
class supercolliderPatch : public dependent {
public:
using dependent::dependent;
void start();
void stop();
};
So ideally what I would want is something like (pseudocode):
launchable *sclang = launchableFactory.create("exec",ARGS); // returns a standalone
launchable *patch = launchableFactory.create("supercolliderPatch",sclang,ARGS) // returns a dependable, with dependency set to sclang
And these launchable *instance would be stored within a std::vector.
Essentially my question is: am I on a fools errand trying to lump these two concepts of standalone/dependent into one or can the factory pattern work for me?
Abstract Factory let's you do exactly that: Construct some concrete instance and treat it as it's abstract interface.
If you can't find a common interface to work with both classes then you might want to reconsider your design, tho it doesn't seem like that's a problem in your case.
You can try this, some of the functional programming, but it may have some minimal performance negative impact. Also it requires C++11 or later
std::function<shared_ptr<Base>()> funcs[] = { [](){ return shared_ptr<Base>(new A()); }, [](){ return shared_ptr<Base>(new B()); } };
Then call:
funcs[i]();
You can for safety, use something like array.
std::array<std::function<shared_ptr<Base>()>, 2> funcs[] =
{ [](){ return shared_ptr<Base>(new A()); }, [](){ return shared_ptr<Base>(new B()); } };
(funcs->at(i)();
This "array of functions" are something like Abstract Factory that returns a shared pointer of the base class.
I will start with my design:
class IOutputBlock{
public:
virtual void write(char *) = 0;
virtual bool hasMemory() = 0;
virtual void openToWrite() = 0;
};
class IInputBlock{
public:
virtual bool hasNext() = 0;
virtual IField *next() = 0;
virtual void openToRead() = 0;
};
class MultiplicationNode : public OperationNode
{
public:
MultiplicationNode(Node *l, Node *r);
~MultiplicationNode(void);
virtual bool hasNext();
IInputBlock * evaluate();
};
class IOBlock: public IInputBlock, public IOutputBlock{
virtual void write(char *);
virtual bool hasMemory();
virtual void openToWrite();
virtual bool hasNext();
virtual IField *next();
virtual void openToRead();
};
Inside the evaluate method i need to create an IOuputBlock to write data in the block.
I want the MultiplicationNode consumer just see method for iterate over the block (IInputBlock interface).
But in the return of evaluate method, I have to perform a typecast.
Is this implementation correct? Or is it an example of bad design?
Can u suggest another design? Or maybe design pattern to help.
IInputBlock * MultiplicationNode::evaluate()
{
IOutputBlock *outputBlock = new IOBlock();
//need to write to outputblock
return (IInputBlock *)outputBlock;
}
I could also do this below, but I don't think it is right, because i was violation "program to an interface", and exposing unnecessary methods inside evaluate method from IInputBlock interface.
IInputBlock * MultiplicationNode::evaluate()
{
IOBlock *outputBlock = new IOBlock();
//need to write to outputblock
return outputBlock;
}
One option is to separate read and write classes (even if underlying data is shared):
class WriteOnlyBlock: public IOutputBlock{
// return new instance of something like ReadOnlyBlock
// potentially tied to same internal data
public: IInputBlock AsRead()...
}
This way you make conversion explicit and prevent callers from attempting to cast IInputBlock to IOutputBlock and minimize number of extra methods exposed by each class.
BIG EDIT
So after gathering some feedback from all of you, and meditating on the XY problem as Zack suggested, I decided to add another code example which illustrates exactly what I'm trying to accomplish (ie the "X") instead of asking about my "Y".
So now we are working with cars and I've added 5 abstract classes: ICar, ICarFeatures, ICarParts, ICarMaker, ICarFixer. All of these interfaces will wrap or use a technology-specific complex object provided by a 3rd party library, depending on the derived class behind the interface. These interfaces will intelligently manage the life cycle of the complex library objects.
My use case here is the FordCar class. In this example, I used the Ford library to access classes FordFeatureImpl, FordPartsImpl, and FordCarImpl. Here is the code:
class ICar {
public:
ICar(void) {}
virtual ~ICar(void) {}
};
class FordCar : public ICar {
public:
ICar(void) {}
~FordCar(void) {}
FordCarImpl* _carImpl;
};
class ICarFeatures {
public:
ICarFeatures(void) {}
virtual ~ICarFeatures(void) {}
virtual void addFeature(UserInput feature) = 0;
};
class FordCarFeatures : public ICarFeatures{
public:
FordCarFeatures(void) {}
virtual ~FordCarFeatures(void) {}
virtual void addFeature(UserInput feature){
//extract useful information out of feature, ie:
std::string name = feature.name;
int value = feature.value;
_fordFeature->specialAddFeatureMethod(name, value);
}
FordFeatureImpl* _fordFeature;
};
class ICarParts {
public:
ICarParts(void) {}
virtual ~ICarParts(void) {}
virtual void addPart(UserInput part) = 0;
};
class FordCarParts :public ICarParts{
public:
FordCarParts(void) {}
virtual ~FordCarParts(void) {}
virtual void addPart(UserInput part) {
//extract useful information out of part, ie:
std::string name = part.name;
std::string dimensions = part.dimensions;
_fordParts->specialAddPartMethod(name, dimensions);
}
FordPartsImpl* _fordParts;
};
class ICarMaker {
public:
ICarMaker(void) {}
virtual ~ICarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts) = 0;
};
class FordCarMaker {
public:
FordCarMaker(void) {}
virtual ~FordCarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts){
FordFeatureImpl* fordFeatures = dynamic_cast<FordFeatureImpl*>(features);
FordPartsImpl* fordParts = dynamic_cast<FordPartsImpl*>(parts);
FordCar* fordCar = customFordMakerFunction(fordFeatures, fordParts);
return dynamic_cast<ICar*>(fordCar);
}
FordCar* customFordMakerFunction(FordFeatureImpl* fordFeatures, FordPartsImpl* fordParts) {
FordCar* fordCar = new FordCar;
fordCar->_carImpl->specialFeatureMethod(fordFeatures);
fordCar->_carImpl->specialPartsMethod(fordParts);
return fordCar;
}
};
class ICarFixer {
public:
ICarFixer(void) {}
virtual ~ICarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) = 0;
};
class FordCarFixer {
public:
FordCarFixer(void) {}
virtual ~FordCarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) {
FordCar* fordCar = dynamic_cast<FordCar*>(car);
FordPartsImpl* fordParts = dynamic_cast<FordPartsImpl*>(parts);
customFordFixerFunction(fordCar, fordParts);
}
customFordFixerFunction(FordCar* fordCar, FordPartsImpl* fordParts){
fordCar->_carImpl->specialRepairMethod(fordParts);
}
};
Notice that I must use dynamic casting to access the technology-specific objects within the abstract interfaces. This is what makes me think I'm abusing inheritance and provoked me to ask this question originally.
Here is my ultimate goal:
UserInput userInput = getUserInput(); //just a configuration file ie XML/YAML
CarType carType = userInput.getCarType();
ICarParts* carParts = CarPartFactory::makeFrom(carType);
carParts->addPart(userInput);
ICarFeatures* carFeatures = CarFeaturesFactory::makeFrom(carType);
carFeatures->addFeature(userInput);
ICarMaker* carMaker = CarMakerFactory::makeFrom(carType);
ICar* car = carMaker->makeCar(carFeatures, carParts);
UserInput repairSpecs = getUserInput();
ICarParts* replacementParts = CarPartFactory::makeFrom(carType);
replacementParts->addPart(repairSpecs);
ICarFixer* carFixer = CarFixerFactory::makeFrom(carType);
carFixer->fixCar(car, replacementParts);
Perhaps now you all have a better understanding of what I'm trying to do and perhaps where I can improve.
I'm trying to use pointers of base classes to represent derived (ie Ford) classes, but the derived classes contain specific objects (ie FordPartsImpl) which are required by the other derived classes (ie FordCarFixer needs a FordCar and FordPartsImpl object). This requires me to use dynamic casting to downcast a pointer from the base to its respective derived class so I can access these specific Ford objects.
My question is: am I abusing inheritance here? I'm trying to have a many-to-many relationship between the workers and objects. I feel like I'm doing something wrong by having an Object family of class which literally do nothing but hold data and making the ObjectWorker class have to dynamic_cast the object to access the insides.
That is not abusing inheritance... This is abusing inheritance
class CSNode:public CNode, public IMvcSubject, public CBaseLink,
public CBaseVarObserver,public CBaseDataExchange, public CBaseVarOwner
Of which those who have a C prefix have huge implementations
Not only that... the Header is over 300 lines of declarations.
So no... you are not abusing inheritance right now.
But this class I just showed you is the product of erosion. I'm sure the Node as it began it was a shinning beacon of light and polymorphism, able to switch smartly between behavior and nodes.
Now it has become a Kraken, a Megamoth, Cthulu itself trying to chew my insides with only a vision of it.
Heed this free man, heed my counsel, beware of what your polymorphism may become.
Otherwise it is fine, a fine use of inheritance of something I suppose is an Architecture in diapers.
What other alternatives do I have if I want to only have a single work() method?
Single Work Method... You could try:
Policy Based Design, where a policy has the implementation of your model
A Function "work" that it is used by every single class
A Functor! Instantiated in every class that it will be used
But your inheritance seems right, a single method that everyone will be using.
One more thing....I'm just gonna leave this wiki link right here
Or maybe just copy paste the wiki C++ code... which is very similar to yours:
#include <iostream>
#include <string>
template <typename OutputPolicy, typename LanguagePolicy>
class HelloWorld : private OutputPolicy, private LanguagePolicy
{
using OutputPolicy::print;
using LanguagePolicy::message;
public:
// Behaviour method
void run() const
{
// Two policy methods
print(message());
}
};
class OutputPolicyWriteToCout
{
protected:
template<typename MessageType>
void print(MessageType const &message) const
{
std::cout << message << std::endl;
}
};
class LanguagePolicyEnglish
{
protected:
std::string message() const
{
return "Hello, World!";
}
};
class LanguagePolicyGerman
{
protected:
std::string message() const
{
return "Hallo Welt!";
}
};
int main()
{
/* Example 1 */
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish> HelloWorldEnglish;
HelloWorldEnglish hello_world;
hello_world.run(); // prints "Hello, World!"
/* Example 2
* Does the same, but uses another language policy */
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman> HelloWorldGerman;
HelloWorldGerman hello_world2;
hello_world2.run(); // prints "Hallo Welt!"
}
More important questions are
How are you going to use an Int Object with your StringWorker?
You current implementation won't be able to handle that
With policies it is possible.
What are the possible objects?
Helps you define if you need this kind of behavior
And remember, don't kill a chicken with a shotgun
Maybe your model will never really change overtime.
You have committed a design error, but it is not "abuse of inheritance". Your error is that you are trying to be too generic. Meditate upon the principle of You Aren't Gonna Need It. Then, think about what you actually have. You don't have Objects, you have Dogs, Cats, and Horses. Or perhaps you have Squares, Polygons, and Lines. Or TextInEnglish and TextInArabic. Or ... the point is, you probably have a relatively small number of concrete things and they probably all go in the same superordinate category. Similarly, you do not have Workers. On the assumption that what you have is Dogs, Cats, and Horses, then you probably also have an Exerciser and a Groomer and a Veterinarian.
Think about your concrete problem in concrete terms. Implement only the classes and only the relationships that you actually need.
The point is that you're not accessing the specific functionality through the interfaces. The whole reason for using interfaces is that you want all Cars to be made, fixed and featured ... If you're not going to use them in that way, don't use interfaces (and inheritance) at all, but simply check at user input time which car was chosen and instantiate the correct specialized objects.
I've changed your code a bit so that only at "car making" time there will be an upward dynamic_cast. I would have to know all the things you want to do exactly to create interfaces I would be really happy with.
class ICar {
public:
ICar(void) {}
virtual ~ICar(void) {}
virtual void specialFeatureMethod(ICarFeatures *specialFeatures);
virtual void specialPartsMethod(ICarParts *specialParts);
virtual void specialRepairMethod(ICarParts *specialParts);
};
class FordCar : public ICar {
public:
FordCar(void) {}
~FordCar(void) {}
void specialFeatureMethod(ICarFeatures *specialFeatures) {
//Access the specialFeatures through the interface
//Do your specific Ford stuff
}
void specialPartsMethod(ICarParts *specialParts) {
//Access the specialParts through the interface
//Do your specific Ford stuff
}
void specialRepairMethod(ICarParts *specialParts) {
//Access the specialParts through the interface
//Do your specific Ford stuff
}
};
class ICarFeatures {
public:
ICarFeatures(void) {}
virtual ~ICarFeatures(void) {}
virtual void addFeature(UserInput feature) = 0;
};
class FordCarFeatures : public ICarFeatures{
public:
FordCarFeatures(void) {}
~FordCarFeatures(void) {}
void addFeature(UserInput feature){
//extract useful information out of feature, ie:
std::string name = feature.name;
int value = feature.value;
_fordFeature->specialAddFeatureMethod(name, value);
}
FordFeatureImpl* _fordFeature;
};
class ICarParts {
public:
ICarParts(void) {}
virtual ~ICarParts(void) {}
virtual void addPart(UserInput part) = 0;
};
class FordCarParts :public ICarParts{
public:
FordCarParts(void) {}
~FordCarParts(void) {}
void addPart(UserInput part) {
//extract useful information out of part, ie:
std::string name = part.name;
std::string dimensions = part.dimensions;
_fordParts->specialAddPartMethod(name, dimensions);
}
FordPartsImpl* _fordParts;
};
class ICarMaker {
public:
ICarMaker(void) {}
virtual ~ICarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts) = 0;
};
class FordCarMaker {
public:
FordCarMaker(void) {}
~FordCarMaker(void) {}
ICar* makeCar(ICarFeatures* features, ICarParts* parts){
return customFordMakerFunction(features, parts);
}
ICar* customFordMakerFunction(ICarFeatures* features, ICarParts* parts) {
FordCar* fordCar = new FordCar;
fordCar->specialFeatureMethod(features);
fordCar->specialPartsMethod(parts);
return dynamic_cast<ICar*>(fordCar);
}
};
class ICarFixer {
public:
ICarFixer(void) {}
virtual ~ICarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) = 0;
};
class FordCarFixer {
public:
FordCarFixer(void) {}
~FordCarFixer(void) {}
void fixCar(ICar* car, ICarParts* parts) {
customFordFixerFunction(car, parts);
}
void customFordFixerFunction(ICar* fordCar, ICarParts *fordParts){
fordCar->specialRepairMethod(fordParts);
}
};
One can do better (for certain values of "better"), with increased complexity.
What is actually being done here? Let's look point by point:
There's some object type, unknown statically, determined at run time from a string
There's some worker type, also unknown statically, determined at run time from another string
Hopefully the object type and the worker type will match
We can try to turn "hopefully" into "certainly" with some template code.
ObjectWorkerDispatcher* owd =
myDispatcherFactory->create("someWorker", "someObject");
owd->dispatch();
Obviously both object and worker are hidden in the dispatcher, which is completely generic:
class ObjectWorkerDispatcher {
ObjectWorkerDispatcher(string objectType, string workerType) { ... }
virtual void dispatch() = 0;
}
template <typename ObjectType>
class ConcreteObjectWorkerDispatcher : public ObjectWorkerDispatcher {
void dispatch () {
ObjectFactory<ObjectType>* of = findObjectFactory(objectTypeString);
WorkerFactory<ObjectType>* wf = findWorkerFactory(workerTypeString);
ObjectType* obj = of->create();
Worker<ObjectType>* wrk = wf->create();
wrk->doWork(obj);
}
map<string, ObjectFactory<ObjectType>*> objectFactories;
map<string, WorkerFactory<ObjectType>*> workerFactories;
ObjectFactory<ObjectType>* findObjectFactory(string) { .. use map }
WorkerFactory<ObjectType>* findWorkerFactory(string) { .. use map }
}
We have different unrelated types of Object. No common Object class, but we can have e.g. several subtypes of StringObject, all compatible with all kinds of StringWorker.
We have an abstract Worker<ObjectType> class template and concrete MyStringWorker : public Worker<StringObject> , OtherStringWorker : public Worker<StringObject> ... classes.
Both kinds of factories are inheritance-free. Different types of factories are kept completely separate (in different dispatchers) and never mix.
There's still some amount of blanks to fill in, but hopefully it all should be more or less clear.
No casts are used in making of this design. You decide whether this property alone is worth such an increase in complexity.
I think you have the right solution per your needs. One thing I see that can be improved is removing the use of carType from the function that deals with the objects at the base class level.
ICar* FordCarFixer::getFixedCar(UserInput& userInput)
{
FordCarParts* carParts = new FordPartFactory;
carParts->addPart(userInput);
FordCarFeatures* carFeatures = new FordCarFeatures;
carFeatures->addFeature(userInput);
FordCarMaker* carMaker = new FordCarMaker;
FordCar* car = carMaker->makeCar(carFeatures, carParts);
UserInput repairSpecs = getUserInput();
ForCarParts* replacementParts = new ForCarParts;
replacementParts->addPart(repairSpecs);
FordCarFixer* carFixer = new FordCarFixer;
carFixer->fixCar(car, replacementParts);
return car;
}
UserInput userInput = getUserInput();
ICar* car = CarFixerFactory::getFixedCar(userInput);
With this approach, most of the objects at FordCarFixer level are Ford-specific.