C++ Components based class - c++

Hi,
I'm writing a component based class with a container, but after thinking of many different approaches, I can't find one that follows really what I want.
Here is an example of the general idea :
And the code I already wrote :
// Abstract class Component
class Component
{
public :
virtual ~Component() = 0;
virtual int GetResult() = 0;
};
class AddComponent : Component
{
public :
int GetResult() { return input1->GetResult() + input2->GetResult(); }
void SetInput1(Component* c) { input1 = c; }
void SetInput2(Component* c) { input2 = c; }
private :
Component* input1;
Component* input2;
};
class ConstComponent : Component
{
public :
int GetResult() { return value; }
void SetValue(int x) { value = x; }
private :
int value;
};
class SignComponent : Component
{
public :
int GetResult() { return sign(input->GetResult()); }
void SetInput(Component* c) { input = c; }
private :
Component* input;
};
class Container
{
public :
Container();
~Container();
void SetRootComponent(Component* c) { rootComponent = c; }
int GetResult() { return rootComponent->GetResult(); }
AddComponent* AddComponentAdd();
ConstComponent* ConstComponentAdd();
SignComponent* SignComponentAdd();
private :
Component* rootComponent;
std::vector<Component*> components;
};
void main(void)
{
// Create container
Container container = Container();
// Create components
SignComponent* cSign = container.AddComponentSign();
AddComponent* cAdd = container.AddComponentAdd();
ConstComponent* cConst1 = container.AddComponentConst();
ConstComponent* cConst2 = container.AddComponentConst();
// Link components
cSign->SetInput(cAdd);
cAdd->SetInput1(cConst1);
cAdd->SetInput2(cConst2);
cConst1->SetValue(-5);
cConst2->SetValue(3);
// Set root component for container
container.SetRootComponent(cSign);
// Compute
int result = container.GetResult();
}
This doesn't even compile, because of the cast of "XComponent" to "Component", which is abstract. I'm pretty sure there is a much better (and simpler ?) way to do it anyway, but I'm out of ideas.

The default inheritance for class is private:
class ConstComponent : Component
For all subclasses of Component you need public inheritance:
class ConstComponent : public Component
if you are attempting to insert new instances of the subclasses into the std::vector<Component*> (which I think you are).
private inheritance is not an is-a relationship, but is a has-a relationship. See How are "private inheritance" and "composition" similar? .

Related

Why does parent class pointer has wrong data when casted from child pointer to parent pointer?

Here is the class hierarchy that I have.
class EventA {/* adds itself to list */};
class EventB {/* adds itself to list */};
class EventC {/* adds itself to list */};
class EventD {/* adds itself to list */};
class EventE {/* adds itself to list */};
class EventF {/* adds itself to list */};
class EventG {/* adds itself to list */};
class EventH {/* adds itself to list */};
class Component : public EventA, public EventB, public EventC, public EventD {
// Propeties and functions
bool sentinel;
};
class CustomComponent : public Component {
// Propeties and functions
};
class UserComponent : public CustomComponent, public EventE, public EventF, public EventG, public EventH {
// Propeties and functions
};
I have a list of each type: EventE, EventF, EventG, EventH. They are added to the list through the constructor when I create the UserComponent object. The problem that I am running into is that when I iterate through the list of EventE, EventF, EventG and EventH, when I cast the pointer from either EventE, EventF, EventG or EventH to Component* some of the properties are not correct when interpreted as such a pointer. For example, sometimes my bool sentinel value will be true(216) when they are supposed to be false. My suspicion is that when I convert the pointer, it does not offset the memory to match the class hierarchy that I have laid out. In other words, I think it is not reading from correct memory address. Is anyone familiar with this issue? My problem is at system design level, so any off-topic solution, or any solution that has a different approach are welcome.
Response to Requested Minimal Example
This code is a minimal example of the problem that I am having. I provided it as requested in the comment section.
#include <iostream>
using namespace std;
class EventA {
public:
char a;
EventA() {
a = 'a';
}
~EventA() {
}
};
class EventB {
public:
char b;
EventB() {
b = 'b';
}
~EventB() {
}
};
class EventC {
public:
char c;
EventC() {
c = 'c';
}
~EventC() {
}
};
class EventD {
public:
char d;
EventD() {
d = 'd';
}
~EventD() {
}
};
class EventE {
public:
char e;
EventE() {
e = 'e';
}
~EventE() {
}
};
class EventF {
public:
char f;
EventF() {
f = 'f';
}
~EventF() {
}
};
class EventG {
public:
char g;
EventG() {
g = 'g';
}
~EventG() {
}
};
class EventH {
public:
char h;
EventH() {
h = 'h';
}
~EventH() {
}
};
class Component : public EventA, public EventB, public EventC, public EventD {
public:
int customValue;
Component() {
customValue = 1000;
}
~Component() {
}
};
class CustomComponent : public Component {
public:
int customComponentValue;
CustomComponent() {
customComponentValue = 2000;
}
~CustomComponent() {
}
};
class UserComponent : public CustomComponent, public EventE, public EventF, public EventG, public EventH {
public:
int userComponentValue;
UserComponent() {
userComponentValue = 3000;
}
~UserComponent() {
}
};
int main() {
UserComponent userComponent = UserComponent();
EventE* ptrEventE = (EventE*)&userComponent;
Component* ptrComponent = (Component*)ptrEventE;
cout << ptrComponent->customValue << endl;
}
If you go into debug mode and inspect the value of ptrComponent you will see exactly what I am talking about. Note that the casting that I made is exactly what is going on at different points of my system. That is why I did it the way I did.
The error is caught if you use static_cast instead of a C-style cast:
a.cpp: In function 'int main()':
a.cpp:134:31: error: invalid 'static_cast' from type 'EventE*' to type 'Component*'
134 | Component* ptrComponent = static_cast<Component*>(ptrEventE);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EventE is not a base of Component, so the compiler does not know how the two are connected. In your case, they're connected by the common derived UserComponent, by there may be other common derived classes with different layouts as well, so it's of no help. static_cast throws an error in that case, C-style cast just does reinterpret_cast and assumes that no pointer modifications are needed.
Two ways to fix: either make Component derive from EventE as well or cast through a known common derived class:
int main() {
UserComponent userComponent = UserComponent();
EventE* ptrEventE = static_cast<EventE*>(&userComponent);
Component* ptrComponent = static_cast<UserComponent*>(ptrEventE); // UserComponent --> Component is implicit
cout << ptrComponent->customValue << endl;
}

Architecture of sub-classes in C++

I learn C++ OOP-paradigm and want to ask related question:
Assumption
We have a base class:
class Base {
public:
virtual SomeType PowerMethod() { return SomeType{} };
}
We have a variable target and subclass which realizes some calculations with target variable based on the constructor's parameter (simple calculations or complicated calcs):
class Calc : public Base {
public: // using only public access to simplify real code structure
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
Question
How to optimally realize two classes which based on different methods (Simple or Complex) but provide the same functionality of PowerMethod()?
My solution
class SimpleCalc : public Calc {
bool isSimple = true;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
class ComplexCalc : public Calc {
bool isSimple = false;
public:
SomeType PowerMethod() override {
Calc CalcInstance(isSimple);
return CalcInstance.target;
};
};
This solution is pretty "ugly" and I want to ask you how to make it more readable.
Thank you!
I think that in your code, you didn't mean to craete a new Calc object, but instead call it on the superclass. This can be done like so:
Calc::Simple();
You can override the method PowerMethod, but still call the superclass's code:
virtual SomeType PowerMethod() override {
//do something
Base::PowerMethod();
}
If your problem is more complicated, and polymorphism and superclasses can't help you, you can always declare some method protected, so that only subclasses can access it. So, you could for example do this:
class Calc : public Base {
protected:
SomeType target;
void Simple() { target = 1; };
void Complex(){ target = 10000; };
public:
explicit Calc(bool isSimple) {
if(isSimple)
Simple();
else
Complex();
}
};
class SimpleCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Simple();
return Calc::target;
};
};
class ComplexCalc : public Calc {
public:
SomeType PowerMethod() override {
Calc::Complex();
return Calc::target;
};
};
If your target is to learn OOP then you can use a factory design pattern to create your final calculator based on isSimple condition:
#include <iostream>
class Base
{
public:
Base()
{
target = 0;
}
int target;
virtual void PowerMethod() = 0;
};
class SimpleCalc : public Base
{
virtual void PowerMethod() { target = 0; }
};
class ComplexCalc : public Base
{
virtual void PowerMethod() { target = 1000; }
};
class CalcFactory
{
public:
virtual Base* createCalc(bool isSimple)
{
if (isSimple)
return new SimpleCalc();
else
return new ComplexCalc();
}
};
int main()
{
CalcFactory factory;
Base * base1 = factory.createCalc(true);
Base * base2 = factory.createCalc(false);
base1->PowerMethod();
base2->PowerMethod();
std::cout << base1->target << std::endl;
std::cout << base2->target << std::endl;
}

Is there a better design practice than to add a new virtual function in base that is not implemented by all derived classes

I have class hierarchy as shown below. It's a simplified version of actual code.
class Base
{
public :
// user_define_type is a output parameter
virtual void Fill(user_define_type);
}
class A : public Base
{
public :
void Fill(user_define_type) override;
}
class B : public Base
{
public :
void Fill(user_define_type) override;
}
I am overriding Fill() method as I need different formatting in both derived classes. Now I have to write one more class deriving from "Base" as it has common functionality. Now my problem is that new class will have to implement Fill() that will operate on different user defined type. As I am returning base class pointer from factory so new Fill() has to be virtual in base but that means I have to add it's definition in older classes "A" and "B" and throw not supported exception from them. This is not a good design. Any better design you guys can suggest ? Thanks in advance.
I believe you need to create a common base class for your user_defined_types in order to achieve this. I also think this could be a good place to use the strategy pattern.
Basically, you create
class user_defined_type_base
{
...
}
class user_defined_type_derived : public user_defined_type_base
{
...
}
class DoSomething
{
private:
DoSomethingStrategy *strategy;
public:
DoSomething(DoSomethingStrategy *strategy) { this->strategy = strategy; }
void Fill(user_defined_type_base *type) { this->strategy->Fill(type); }
}
class DoSomethingStrategy
{
public:
virtual void Fill(user_defined_type_base *obj) = 0;
}
class DoSomethingStrategyA : public DoSomethingStrategy
{
public:
void Fill(user_defined_type_base *obj)
{
...
}
}
class DoSomethingStrategyB : public DoSomethingStrategy
{
public:
void Fill(user_defined_type_base *obj)
{
...
}
}
class DoSomethingStrategyC : public DoSomethingStrategy
{
public:
void Fill(user_defined_type_base *obj)
{
...
}
}
void main()
{
DoSomethingStrategy *strategy = new DoSomethingStragegyA();
DoSomething *dosomething = new DoSomething(strategy);
user_defined_type_base *type = new user_defined_type_base();
dosomething->Fill(type);
DoSomethingStrategy *strategyC = new DoSomethingStragegyC();
DoSomething *dosomethingC = new DoSomething(strategyC);
user_defined_type_base *typeC = new user_defined_type_derived();
dosomethingC->Fill(typeC);
}

How To Have A Single Interface Return Different Data Types?

In a nutshell, I want to use a single interface, IProducer, to create an object, IProduct. IProduct will have different components depending on which interface created it. The IProduct class will then be used by the IConsumer interface. The correct IConsumer class should be used (I do not want to do type checking myself) based on the derived type of IProduct.
I would essentially like to use the Strategy pattern (different behaviors behind a single interface), but with the added ability to return an object specific to the derived interface used. I want to abide by the Open/Close principle and not alter any of these existing classes when more functionality is added.
I would like to accomplish something like this (I'm sure the syntax is wrong somewhere but bear with me):
class IProduct {
public:
int intData;
};
class ProductA : public IProduct {
public:
float floatData;
};
class ProductB : public IProduct {
public:
bool boolData;
};
class IProducer {
public:
virtual IProduct* produce(void) = 0;
};
class ProducerA : public IProducer {
public:
IProduct* produce(void) {
return new ProductA;
}
};
class ProducerB : public IProducer {
public:
IProduct* produce(void) {
return new ProductB;
}
};
class IConsumer {
public:
virtual void consume(IProduct* prod) = 0;
};
class ConsumerA : public IConsumer {
public:
void consume(IProduct* prod) {
//I want to access the float!
}
};
class ConsumerB : public IConsumer {
public:
void consume(IProduct* prod) {
//I want to access the bool!
}
};
void main() {
IProducer* producer = ProducerFactory::create("ProducerA");
IProduct* product = producer->produce();
IConsumer* consumer = ConsumerFactory::create("ConsumerA");
consumer->consume(product); //I would like the correct consumer to be used here to deal with the ProductA class
}
If you think there is a better way to go about this I'm all ears. Thanks for your help!
What you need is a registry which maps IProduct implementations to the right IConsumer implementations. Basically its just an abstraction of a map:
class ConsumerRegistry
{
std::map<size_t, std::shared_ptr<IConsumer>> m_consumers;
public:
// we are not responsible for products, so lets allow plain ptrs here for more flexibility and less overhead
std::shared_ptr<IConsumer> GetConsumer(IProduct* product)
{
auto it = m_consumers.find(typeid(product).hash_code());
if (it == m_consumers.end())
return nullptr;
else
return it->second;
}
template<typename P>
void RegisterConsumer(std::shared_ptr<IConsumer> consumer)
{
m_consumers.emplace(typeid(P).hash_code(), consumer);
}
template<typename P>
void UnregisterConsumer()
{
m_consumers.erase(typeid(P).hash_code());
}
};
Either expose this class globally (e.g as singleton) or use it in the contexts where you need it. You register consumers like this:
reg.RegisterConsumer<ProductA>(new ConsumerA());
reg.RegisterConsumer<ProductB>(new ConsumerB());
We could also have a virtual void Register(ConsumerRegistry& reg) = 0; method inside IConsumer allowing for safer registering:
void ConsumerA::Register(ConsumerRegistry& reg, std::shared_ptr<IConsumer> self)
{
IConsumer::Register<ProductA>(reg, self);
}
// Required for friendship, can be static:
template<typename T>
void IConsumer::Register(ConsumerRegistry& reg, std::shared_ptr<IConsumer> self)
{
reg->RegisterConsumer<T>(self);
}
void ConsumberRegistry::RegisterConsumer(std::shared_ptr<IConsumer> consumer)
{
consumer->Register(*this, consumer);
}
Make both Register() and the low-level RegisterConsumer() methods private and let ConsumerRegistry and IConsumer be friends. Can be used like this then:
reg.RegisterConsumer(new ConsumerA());
reg.RegisterConsumer(new ConsumerB());
This is a solution I'm thinking of using. I'd appreciate any feedback.
I'm going to use the Visitor pattern and introduce the ProductVisitor class like so:
class IProductVisitor {
public:
explicit IProductVisitor() {}
virtual ~IProductVisitor(){}
virtual void visitA(ProductA* model) = 0;
virtual void visitB(ProductB* model) = 0;
};
class ProductTypeVisitor : public IProductVisitor {
public:
typedef enum {Unknown, A, B} ProductType;
explicit ProductTypeVisitor() : modelType(Unknown) {}
virtual ~ProductTypeVisitor(){}
virtual void visitA(ProductA* product) {
modelType = A;
}
virtual void visitB(ProductB* product) {
modelType = B;
}
ProductType getProductType(void) {
return modelType;
}
ProductType modelType;
};
class IProduct {
public:
IProduct() : intData(3) {}
virtual ~IProduct(){}
int intData;
virtual void accept(IProductVisitor* v) = 0;
};
class ProductA : public IProduct {
public:
ProductA() : IProduct(), floatData(5.5) { }
virtual ~ProductA(){}
float floatData;
void accept(IProductVisitor* v) {
v->visitA(this);
}
};
class ProductB : public IProduct {
public:
ProductB() : IProduct(),boolData(false) { }
virtual ~ProductB(){}
bool boolData;
void accept(IProductVisitor* v) {
v->visitB(this);
}
};
When making my factory, ConsumerFactor, I will use the ProductTypeVisitor class to determine what class the product is, dynamically cast it correctly (based off of the state of the enum), and then return a consumer initialized with the correct product.
class ConsumerFactory {
public:
explicit ConsumerFactory(void) {}
IConsumer* createFromProduct(IProduct* product) {
ProductTypeVisitor visitor;
product->accept(&visitor);
ProductTypeVisitor::ProductType productType = visitor.getProductType();
IConsumer* consumerPtr;
switch (productType) {
case ProductTypeVisitor::A :
consumerPtr = new ConsumerA(dynamic_cast<ProductA*>(product));
break;
case ProductTypeVisitor::B :
consumerPtr = new ConsumerB(dynamic_cast<ProductB*>(product));
break;
default:
std::cout << "Product type undefined. (throw exception)" << std::endl;
break;
}
return consumerPtr;
}
private:
ProductTypeVisitor visitor;
};
Finally, the code will look like this:
IProducer* producer = new ProducerA;
IProduct* product = producer->produce();
ConsumerFactory factory;
IConsumer* consumer = factory.createFromProduct(product);
consumer->consume();
Where the only thing that was ever specified, was ProducerA. Which, in my case, is the only thing that should be specified by the user. Also, I've isolated change areas to just two classes, the ConsumerFactory, and the IProductVisitor (which are very small changes to begin with).
If anyone could offer improvements or suggestions I'm all ears!
This is not the full solution (and maybe just a curiosity) but you can always do the tracking of types at compile time and use a bridging templated call to dispatch a product to the correct consumer.
#include <iostream>
template <class T>
class IProduct {
public:
virtual ~IProduct() {}
int intData;
typedef T consumer;
};
class ConsumerA;
class ProductA : public IProduct<ConsumerA> {
public:
float floatData;
};
class ConsumerB;
class ProductB : public IProduct<ConsumerB> {
public:
bool boolData;
};
template <class P, class C>
void apply(P* product, C* consumer) {
dynamic_cast<typename P::consumer*>(consumer)->consume(product);
}
template <class T>
class IConsumer {
public:
virtual void consume(IProduct<T>* prod) = 0;
};
class ConsumerA : public IConsumer<ConsumerA> {
public:
void consume(IProduct<ConsumerA>* prod) {
//I want to access the float!
std::cout << "ConsumerA" << std::endl;
std::cout << dynamic_cast<ProductA*>(prod)->floatData << std::endl;
}
};
class ConsumerB : public IConsumer<ConsumerB> {
public:
void consume(IProduct<ConsumerB>* prod) {
//I want to access the bool!
std::cout << "ConsumerB" << std::endl;
std::cout << dynamic_cast<ProductB*>(prod)->boolData << std::endl;
}
};
int main(int argc, char* argv[]) {
auto p_a = new ProductA;
auto c_a = new ConsumerA;
apply(p_a, c_a);
auto p_b = new ProductB;
auto c_b = new ConsumerB;
apply(p_b, c_b);
return 0;
}
I found this question while trying to solve a analogous issue. I ended up using std::any (which c++17 added to the language) to solve my problem. A single interface can return a std::any which you can cast back into the underlying type (via std::any_cast). In broad terms, std::any is like “hiding” types behind a void* pointer, but done in a type safe way, with full language and compiler support.
See:
std::any: How, when, and why
When should I use std::any
Related topic std::variant.

Generic way to set particular parameters of a polymorphic member variable

Sorry for the convoluted title of my question, conceptually it is quite simple but I can't find any good design to do it.
I have a base class accessible by the end user :
class A {
private:
// m is a functor
Base* m;
};
class Base {
public:
virtual void someInterface();
};
class DerivedT1 : public Base {
public:
virtual void someInterface()
{
some_parameter++;
}
private:
int some_parameter; // how to set?
};
class DerivedT2 : public Base {
public:
virtual void someInterface()
{
some_other_parameter += a_third_parameter;
}
private:
double some_other_parameter; // how to set?
double a_third_parameter; // how to set?
};
And I am trying to find the most generic way to set some_parameter and some_other_parameter from A's public interface.
I have thought of giving a number to my parameters but this sounds really ugly.
Is there any beautiful, object-oriented way to do this ?
you want to use A's public interface to set derived class parameters:
you can define a public function In A, which have a Base* parameter:
class A
{
public:
void setter(const Base *p);
{
m = p;
}
};
if you want to set Drived1 you can define a object of Derived1, can pass it to setter;
I think you want to pass value using A's public function, you must know the type of pointer of Base*,so you can pass value by the constructor of Derived1 or Derived2!
I nothing else works, you could always use a dynamic cast:
DerivedT1 *d1 = dynamic_cast<DerivedT1>(m);
if (d1 != nullptr)
{
// do something with derived 1
}
else
{
DerivedT2 *d2 = dynamic_cast<DerivedT2>(m);
if (d2 != nullptr)
{
// do something with derived 2
}
}
But if you need that, it's usually a sign that there is something wrong with your design.
If you want to do something along these lines
A a; a.setAlgorithmFamily(Algorithm::Type1);
a.getAlgorithmImplementation().setSomeParameter(34);
This is a quick and kind of dirty example of how you could do it. A::setAlgorithmType is basically a factory pattern in it's simplest form.
nclude <iostream>
using namespace std;
class Algorithm {
public:
virtual void setParameter(int value) = 0;
};
class AlgoX : public Algorithm {
int mX;
public:
void setParameter(int value) {
cout <<"Setting X to " <<value <<endl;
mX = value;
}
};
class AlgoY : public Algorithm {
int mY;
public:
void setParameter(int value) {
cout <<"Setting Y to " <<value <<endl;
mY = value;
}
};
class A {
public:
void setAlgorithmType(std::string type) {
cout <<"Now using algorithm " <<type <<endl;
if(type == "X")
mAlgorithm = new AlgoX();
else if(type == "Y")
mAlgorithm = new AlgoY();
}
Algorithm* getAlgorithmImplementation() { return mAlgorithm; }
private:
Algorithm* mAlgorithm;
};
int main(int argc, char** argv) {
A a;
a.setAlgorithmType("X");
a.getAlgorithmImplementation()->setParameter(5);
return 0;
}
This gives:
Now using algorithm X
Setting X to 5