Creating Objects of same Class with different Functions at Compiletime - c++

atm I'm trying to find the best solution for creating objects(classes) with common properties but differ in one specific function.
The reason I dont use a simple sub-class is, that I have about 50 "different" objects and I do not want to create a class for each of them.
Here is my attempt to do so:
class module{
public:
//..constructor and stuff
void (*work)();
}
int main(){
module A = new module();
A->work = [](mainclass* m_class) -> void {/*do smth specific */});
//... continue with B,C,...
}
I wonder if this is the most elegant (or most horrible) way to do this, or if there is a better concept for that kind of task.

If the class doesn't have to be exactly the same, use templates
template<void(*work_fn)(mainclass*)>
class module{
public:
//..constructor and stuff
void work(mainclass* p) {work_fn(p);}
};
void work_A(mainclass*) {/*do smth specific */};
int main(){
module<work_A> A; //note, no new
A.work(thingy);
}
If you do have to use exactly the same type (sometimes), then you can use dynamic dispatch on your class:
class module {
public:
//..constructor and stuff
virtual void work(mainclass* p);
};
template<void(*work_fn)(mainclass*)>
class module_impl : public module {
public:
using module;
void work(mainclass* p) {work_fn(p);}
};
void work_A(mainclass*) {/*do smth specific */};
int main(){
std::unique_ptr<module> A(new module_impl<work_A>(););
A->work(thingy);
}
However, this might be overkill. Your idea may indeed be best if they're being stored in a container or whatever.
class module{
public:
//..constructor and stuff
explicit module(std::function<void(mainclass*)> workfunc) : work(std::move(workfunc)) {}
std::function<void(mainclass*)> work;
};
int main(){
module A([](mainclass* m_class) -> void {/*do smth specific */}); //note no new
A.work(thingy);
}

There is a famous software design pattern called the "strategy pattern", which is probably what you want: changing behaviour at runtime. A nice tutorial (although for java, but immediately translatable to C++) is here https://www.youtube.com/watch?v=-NCgRD9-C6o&list=PLF206E906175C7E07&index=3

Related

C++ Functions Select Behavior Based on Passed Parameter Derived Class?

What I'm trying to do is to have a base class that has a primary functionality, as well as multiple derived classes that have various other additional functions/variables. The main functionality of all these derived classes will behave very similarly no matter what object of one of the derived classes is passed to it, but with slight changes based on what the derived class is.
So a background here is that I'm mostly experienced with Fortran programming but am trying to break into C++ more. I'm trying to do something here that is pretty easy in Fortran but am having trouble in C++. Basically my code defining my classes looks something like this
class base_class{
public:
void prim_func(base_class &my_obj);
};
class derived_class_1: public base_class{
public:
int a_func(int arg1);
};
class derived_class_2: public base_class{
public:
double a_func(double arg2);
};
And then the void class method looks something like (right now, I know this isn't right)
void base_class::prim_func(base_class &my_obj){
// a bunch of stuff for all classes
// if my_obj class is derived_class_1
my_obj.a_func(1);
// some more stuff specific to using derived_class_1
// if my_obj class is derived_class_2
my_obj.a_func(1.5);
// some more stuff specific to using derived_class_2
// a bunch of stuff for all classes
}
I want that prim_func to have (slightly) different behaviors based on what the actual derived class that is passed to it is. So the main code would look like this
derived_class_1 def_obj_1;
derived_class_2 def_obj_2;
main(){
def_obj_1.prim_func(def_obj_1);
def_obj_2.prim_func(def_obj_2);
}
So I would like to slightly modify the behavior in this primary functionality based on what the derived class of the passed object actually is. In Fortran there is a SELECT TYPE functionality (https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/s-1/select-type.html) that allows this, but I can't seem to find something similar in C++?
I know one workaround could be to just make one big class that contains overloaded versions of all the different functions, and all the different variables that the various derived class objects would need, and then just have an indicator variable to let it know which functionality it should be using. But this would be extremely inelegant and would potentially cause some other issues, so I would like to avoid it.
You can't do that with plain C++.
You can't have derived classes with overriden functions with different signatures.
What you can do is using templates.
Use a templated Base Class that provides the base function as a pure virtual.
You can then write a wrapper around that function as a template:
template<typename T>
class Base {
public:
virtual T func(T param) = 0;
};
class DerivedA : public Base<int> {
public:
int func(int param) override {
return param;
};
};
class DerivedB : public Base<double> {
public:
double func(double param) override {
return param;
};
};
template<typename T>
T prim_func(Base<T>& base, T param) {
return base.func(param);
}
int main() {
DerivedA a;
DerivedB b;
auto c = prim_func(a,4);
auto d = prim_func(b,4.0);
}
Ok, so it turns out there is a way to do this in C++ it just involves dynamic casting a pointer using the passed object (but it does have to be a polymorphic object). So the way I made it work was doing something like this (comparing to the previous incomplete code I had).
class base_class{
public:
virtual void a_func(){};
void prim_func(base_class &my_obj);
};
class derived_class_1: public base_class{
public:
int a_func(int arg1);
};
class derived_class_2: public base_class{
public:
double a_func(double arg2);
};
void base_class::prim_func(base_class &my_obj){
// a bunch of stuff for all classes
if(derived_class_1* class_ptr = dynamic_cast<derived_class_1*>(&my_obj)){
class_ptr.a_func(1);
// some more stuff specific to using derived_class_1
}
else if(derived_class_2* class_ptr = dynamic_cast<derived_class_2*>(&my_obj)){
class_ptr.a_func(1.5);
// some more stuff specific to using derived_class_2
}
// a bunch of stuff for all classes
}
derived_class_1 def_obj_1;
derived_class_2 def_obj_2;
main(){
def_obj_1.prim_func(def_obj_1);
def_obj_2.prim_func(def_obj_2);
}
To be clear, this still won't compile/work since some of the functions need definitions and what not, but this is a general description of how to do it. A working example can be found in MFEM's code here: https://docs.mfem.org/4.5/amgxsolver_8cpp_source.html#l00859

Grouping two types together

I use a third party library over which I have no control. It contains 2 classes A and B, which both define a method with the same name:
class A {
public:
...
void my_method ();
};
class B {
public:
...
void my_method ();
};
I want to create a class C that contains a member which is of class A or B. Crucially, I can know only at runtime whether I will need A or B. This class C will only call the method my_method.
If I could modify the code, I would simply make A and B derive from a parent class (interface) that defined my_method. But I can't.
What is the simplest/most elegant way to create this class C? I could of course define C in this way:
class C {
public:
void call_my_method() { if (a) a->my_method() else b->my_method(); }
private:
A* a;
B* b;
But I want to avoid paying the cost of the if statement everytime. It also feels inelegant. Is there a way I can create a super type of class A or B? Or any other solution to this problem?
You may use std::function (not sure it has better performance though), something like:
class C {
public:
void call_my_method() { my_method(); }
void use_a(A* a) { my_method = [=]() { a->my_method() }; }
void use_b(B* b) { my_method = [=]() { b->my_method() }; }
private:
std::function<void()> my_method;
};
No; at some point you need branching. The best you can do is to hoist the branching up/down the call stack†, so that more of your program is encapsulated within the figurative if/else construct and the branch itself need be performed less frequently. Of course then you need to duplicate more of your program's source code, which is not ideal.
The only improvement I'd suggest at this time is a construct such as boost::variant. It basically does what you're already doing, but takes up less memory and doesn't have that layer of indirection (using what's called a tagged union instead). It still needs to branch on access, but until profiling has revealed that this is a big bottleneck (and you'll probably find that branch prediction alleviates much of this risk) I wouldn't go any further with your changes.&ddagger;
† I can never remember which way it goes lol
&ddagger; One such change might be to conditionally initialise a function pointer (or modern std::function), then call the function each time. However, that's a lot of indirection. You should profile, but I'd expect it to be slower and harder on the caches. An OO purist might recommend a polymorphic inheritance tree and virtual dispatch, but that's not going to be of any use to you once you care about performance this much.
How about using inheritance with a virtual function, using a 'base class' (C):
class C
{
public:
virtual void do_method() = 0;
};
class D : public C, private A
{
void do_method() { my_method(); }
};
class E : public C, private B
{
void do_method() { my_method(); }
}
Then this will work:
C * d = new D();
d->do_method();
Suggest to wrap your A and B objects into some helper template TProxy which realizes IProxy interface. Class C (or Consumer) will work with IProxy interface and won't know about type of the object inside Proxy
#include <stdio.h>
struct A {
void func () { printf("A::func\n"); }
};
struct B {
void func () { printf("B::func\n"); }
};
struct IProxy
{
virtual void doFunc() = 0;
virtual ~IProxy() {};
};
template<typename T>
struct TProxy : public IProxy
{
TProxy(T& i_obj) : m_obj(i_obj) { }
virtual void doFunc() override { m_obj.func(); }
private:
T& m_obj;
};
class Consumer
{
public:
Consumer(IProxy& i_proxy) : m_proxy(i_proxy) {}
void Func() { m_proxy.doFunc();}
private:
IProxy& m_proxy;
};
Main:
int main()
{
A a;
TProxy<A> aProxy(a);
B b;
TProxy<B> bProxy(b);
Consumer consumerA{aProxy};
consumerA.Func();
Consumer consumerB{bProxy};
consumerB.Func();
return 0;
}
Output:
A::func
B::func

oop - C++ - Proper way to implement type-specific behavior?

Let's say I have a parent class, Arbitrary, and two child classes, Foo and Bar. I'm trying to implement a function to insert any Arbitrary object into a database, however, since the child classes contain data specific to those classes, I need to perform slightly different operations depending on the type.
Coming into C++ from Java/C#, my first instinct was to have a function that takes the parent as the parameter use something like instanceof and some if statements to handle child-class-specific behavior.
Pseudocode:
void someClass(Arbitrary obj){
obj.doSomething(); //a member function from the parent class
//more operations based on parent class
if(obj instanceof Foo){
//do Foo specific stuff
}
if(obj instanceof Bar){
//do Bar specific stuff
}
}
However, after looking into how to implement this in C++, the general consensus seemed to be that this is poor design.
If you have to use instanceof, there is, in most cases, something wrong with your design. – mslot
I considered the possibility of overloading the function with each type, but that would seemingly lead to code duplication. And, I would still end up needing to handle the child-specific behavior in the parent class, so that wouldn't solve the problem anyway.
So, my question is, what's the better way of performing operations that where all parent and child classes should be accepted as input, but in which behavior is dictated by the object type?
First, you want to take your Arbitrary by pointer or reference, otherwise you will slice off the derived class. Next, sounds like a case of a virtual method.
void someClass(Arbitrary* obj) {
obj->insertIntoDB();
}
where:
class Arbitrary {
public:
virtual ~Arbitrary();
virtual void insertIntoDB() = 0;
};
So that the subclasses can provide specific overrides:
class Foo : public Arbitrary {
public:
void insertIntoDB() override
// ^^^ if C++11
{
// do Foo-specific insertion here
}
};
Now there might be some common functionality in this insertion between Foo and Bar... so you should put that as a protected method in Arbitrary. protected so that both Foo and Bar have access to it but someClass() doesn't.
In my opinion, if at any place you need to write
if( is_instance_of(Derived1) )
//do something
else if ( is_instance_of(Derived2) )
//do somthing else
...
then it's as sign of bad design. First and most straight forward issue is that of "Maintainence". You have to take care in case further derivation happens. However, sometimes it's necessary. for e.g if your all classes are part of some library. In other cases you should avoid this coding as far as possible.
Most often you can remove the need to check for specific instance by introducing some new classes in the hierarchy. For e.g :-
class BankAccount {};
class SavingAccount : public BankAccount { void creditInterest(); };
class CheckingAccount : public BankAccount { void creditInterest(): };
In this case, there seems to be a need for if/else statement to check for actual object as there is no corresponsing creditInterest() in BanAccount class. However, indroducing a new class could obviate the need for that checking.
class BankAccount {};
class InterestBearingAccount : public BankAccount { void creditInterest(): } {};
class SavingAccount : public InterestBearingAccount { void creditInterest(): };
class CheckingAccount : public InterestBearingAccount { void creditInterest(): };
The issue here is that this will arguably violate SOLID design principles, given that any extension in the number of mapped classes would require new branches in the if statement, otherwise the existing dispatch method will fail (it won't work with any subclass, just those it knows about).
What you are describing looks well suited to inheritance polymorphicism - each of Arbitrary (base), Foo and Bar can take on the concerns of its own fields.
There is likely to be some common database plumbing which can be DRY'd up the base method.
class Arbitrary { // Your base class
protected:
virtual void mapFields(DbCommand& dbCommand) {
// Map the base fields here
}
public:
void saveToDatabase() { // External caller invokes this on any subclass
openConnection();
DbCommand& command = createDbCommand();
mapFields(command); // Polymorphic call
executeDbTransaction(command);
}
}
class Foo : public Arbitrary {
protected: // Hide implementation external parties
virtual void mapFields(DbCommand& dbCommand) {
Arbitrary::mapFields();
// Map Foo specific fields here
}
}
class Bar : public Arbitrary {
protected:
virtual void mapFields(DbCommand& dbCommand) {
Arbitrary::mapFields();
// Map Bar specific fields here
}
}
If the base class, Arbitrary itself cannot exist in isolation, it should also be marked as abstract.
As StuartLC pointed out, the current design violates the SOLID principles. However, both his answer and Barry's answer has strong coupling with the database, which I do not like (should Arbitrary really need to know about the database?). I would suggest that you make some additional abstraction, and make the database operations independent of the the data types.
One possible implementation may be like:
class Arbitrary {
public:
virtual std::string serialize();
static Arbitrary* deserialize();
};
Your database-related would be like (please notice that the parameter form Arbitrary obj is wrong and can truncate the object):
void someMethod(const Arbitrary& obj)
{
// ...
db.insert(obj.serialize());
}
You can retrieve the string from the database later and deserialize into a suitable object.
So, my question is, what's the better way of performing operations
that where all parent and child classes should be accepted as input,
but in which behavior is dictated by the object type?
You can use Visitor pattern.
#include <iostream>
using namespace std;
class Arbitrary;
class Foo;
class Bar;
class ArbitraryVisitor
{
public:
virtual void visitParent(Arbitrary& m) {};
virtual void visitFoo(Foo& vm) {};
virtual void visitBar(Bar& vm) {};
};
class Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Parent specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitParent(*this);
}
};
class Foo: public Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Foo specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitFoo(*this);
}
};
class Bar: public Arbitrary
{
public:
virtual void DoSomething()
{
cout<<"do Bar specific stuff"<<endl;
}
virtual void accept(ArbitraryVisitor& v)
{
v.visitBar(*this);
}
};
class SetArbitaryVisitor : public ArbitraryVisitor
{
void visitParent(Arbitrary& vm)
{
vm.DoSomething();
}
void visitFoo(Foo& vm)
{
vm.DoSomething();
}
void visitBar(Bar& vm)
{
vm.DoSomething();
}
};
int main()
{
Arbitrary *arb = new Foo();
SetArbitaryVisitor scv;
arb->accept(scv);
}

Is it possible to add class members to base class A from derived class?

I was just thinking about it and wondering if it's totally possible, just out of curiosity, as it would be very usefull I think. (but most of my ideas are crazy/insane anyway).
So here it goes:
Is it possible to create a class A, and class B, then add a member to class A by using class B?
Let's suppose we are making a game, or some program in which this would be usefull:
class Player
{
public:
float health;
};
Now, you think of a way to allow extensions by using include files or something:
#define INCLUDE_SPEEDO_METER
#ifdef INCLUDE_SPEEDO_METER
class PlayerSpeedo : public Player
{
public:
float absolute_speed;
//Do some Magic here & there
};
#endif
Now let's suppose we want to access the absolute speed of a player from the Player class like Player.absolute_speed.
Is this possible in any way?
No, that's not possible. You can't "inject" members into another class. Frankly, I can't see why you would ever want to. No one else than you would be aware of this "injected" member.
While you can't syntactically do what you are hoping to do, you can achieve something very close by storing a map in the base class.
class Player
{
public:
Player(float health = 0) { data["health"] = health; }
float health() const { return get("health"); }
float get(std::string const& field) const { return data[field]; }
protected:
std::map<std::string, float> data;
};
class PlayerSpeedo : public Player
{
public:
PlayerSpeedo(float absolute_speed) {data["absolute_speed" = absolute_speed; }
float absolute_speed() const { return get("absolute_speed"); }
};
What you're talking about is not possible in a statically typed language, but it would work in a dynamically typed language (like Python).
A way of achieving that in C++ would be to use a Map between string names of properties and some generic wrapper for property values.
Not quite what you're asking for, but would give you somewhat similar capabilities is the recent proposal for a future version of the C++ standard Call syntax: x.f(y) vs. f(x,y)
This would enable you to write a standalone function float absolute_speed(const Player& p) { return 0.0f; } that you could call via Player p; auto speed = p.absolute_speed() without changing the definition of Player. This is a similar idea to extension methods in C#.
Maybe you like the way which is often done to extend a base class by another class with a template like the following. There is no need for runtime polymorphism which is often a criteria for speed while optimizing can go down to the executed functions without stopping at the virtual functions.
As you can see from the example, it looks like injection of methods and attributes. C++11 offer it to use the constructor from the class which you use to extend the given class very simple. OK, this is a stupied example but maybe it give you an idea how the thing works.
#include <iostream>
class Empty
{
public:
void DoSomething() { std::cout << "Nothing" << std::endl;}
};
class Extender
{
private:
int x;
public:
Extender(int _x):x(_x) {}
void DoSomething() { std::cout << "Value " << x << std::endl; }
};
template <typename ExtendWith>
class User: public ExtendWith
{
public:
using ExtendWith::ExtendWith;
void DoIt() { ExtendWith::DoSomething(); }
};
int main()
{
User<Empty> userEmpty;
userEmpty.DoIt();
User<Extender> userExtended(100);
userExtended.DoIt();
}
I don't think the language could allow what you're trying to do without introducing inconsistencies.
I don't think you want to modify the actual type though, since what you describe is essentially converting a super-type instance into a sub-type instance. You could do this by adding a constructor to the sub-type...
class PlayerSpeedo : public Player {
public:
float absolute_speed;
explcit PlayerSpeedo(const Player& p, float absolute_speed=0, ...) : health(p.health) {
// copy Player values
}
Another option might be storing a reference to the original object, and decorating it. This doesn't alter the type though.

Access to 'inner' classes in case of composition

I have certain functionality encapsulated in classes which I use in another class. I think this is called composition.
class DoesSomething01
{
public:
DoesSomething01();
void functionality01();
void functionality02();
};
class DoesSomething02
{
public:
DoesSomething02();
void functionality01();
void functionality02();
};
class ClassA
{
public:
ClassA();
private:
DoesSomething01 *m_doesSomething01;
DoesSomething02 *m_doesSomething02;
};
If I have now a ClassB which "knows" ClassA and have to use/execute functionality01 and/or functionality02 of classes DoesSomething01 and/or DoesSomething02 I see two possibilities:
a) Add methods like this to ClassA to provide ClassB direct access to DoesSomething01 and/or DoesSomething02:
DoesSomething01 *getDoesSomething01() { return *m_doesSomething01; }
DoesSomething02 *getDoesSomething02() { return *m_doesSomething02; }
ClassB could then do something like this:
m_classA->getDoesSomething01()->functionality01();
b) Add (in this case four) methods to ClassA which forwards the method calls to DoesSomething01 and DoesSomething02 like this:
void doesSomething01Functionality01() { m_doesSomething01->functionality01(); }
void doesSomething01Functionality02() { m_doesSomething01->functionality02(); }
void doesSomething02Functionality01() { m_doesSomething02->functionality01(); }
void doesSomething02Functionality02() { m_doesSomething02->functionality02(); }
Which option is better and why?
What are the advantages/disadvantages of each option?
First option can be considered a code smell. According to Robert C. Martin's 'Clean Code' it is "Transitive Navigation" and should be avoided. Quoting the author:
In general we don’t want a single module to know much about its
collaborators. More specifically, if A collaborates with B, and B
collaborates with C, we don’t want modules that use A to know about C.
(For example, we don’t want a.getB().getC().doSomething();.)
Second option looks better. It is classical use of Facade pattern. And it is better, because it hides other functionalities of classes DoesSomthing01 and DoesSomthing02. Then you ve'got simplified view of it which is easier to use than 1st option.
Edit: there is also one more thing. You've got two classes which have the same functionalites and are aggregated by other class. You should consider using Stratey pattern here. The your code will look like this:
class DoesSomething
{
public:
virtual void functionality01() = 0;
virtual void functionality02() = 0;
}
class DoesSomething01 : DoesSomething
{
public:
DoesSomething01();
void functionality01();
void functionality02();
};
class DoesSomething02 : DoesSomething
{
public:
DoesSomething02();
void functionality01();
void functionality02();
};
class ClassA
{
public:
ClassA();
DoesSomething* doesSomething(); // Getter
void doesSomething(DoesSomething* newDoesSomething); // Setter
// ...
private:
DoesSomething *m_doesSomething;
};
Then you will need only two method instead of four:
void doesFunctionality01() { m_doesSomething->functionality01(); }
void doesFunctionality02() { m_doesSomething->functionality02(); }
The first scenario is a violation of law of Demeter, which says that a class can only talk to its immediate friends. Basically the problem with the first approach is that any change in the inner classes DoSomething01 and DoSomething02 will trigger a change in Class A as well as Class B because both classes are now directly dependent on these inner classes.
The second option is better as it encapsulates the class B from inner classes but a side effect of this solution is that now class A has a lot of methods that does nothing fancy except for delegating to its inner classes. This is fine but imagine if DoSomething01 has an inner class DoSomething03 and class B needs to access its functionality without directly knowing about it than the class A would need to have another method that would delegate to DoSomething01 that would in turn delegate to DoSomething03. In this case I think it is better to let class B directly know about DoSomething01 otherwise class A is going to have a huge interface that simply delegates to its inner classes.
If there are many classes and/or many methods to be called it makes sense to invent
an interface in the form of an abstract parent class:
class SomeInterface
{
public:
SomeInterface(){}
virtual void functionally01() = 0;
virtual void functionally02() = 0;
}
DoesSomthing01 and other classes would then inherit this class:
class DoesSomthing01 : public SomeInterface
and implement the methods.
If it make sense to associate a key with the instantiation of such a class
you could store these objects in ClassA e.g. using a map (here I
use an integer as the key):
class ClassA
{
private:
std::map<int, SomeInterface*> m_Interfaces;
public:
SomeInterface* getInterface(const int key)
{
std::map<int, SomeInterface*>::iterator it(m_Interfaces.find(key));
if (it != m_Interfaces.end())
return it->second;
else
return NULL;
}
};
From ClassB you could then access them
int somekey = ...;
SomeInterface *myInter = m_classA->getInterface(somekey);
if (myInter)
myInter->functionally01();
This way you have just one access method (getInterface()) independent
of the number of objects.
In order to encode the access to the methods using a key you could
create a map which maps a key onto a closure or a simple switch statement:
in SomeInterface:
public:
void executeMethod(const int key)
{
switch(key)
{
case 1: functionally01(); break;
case 2: functionally01(); break;
default:
// error
}
int methodKey = ...;
int objectKey = ...;
SomeInterface *myInter = m_classA->getInterface(objectKey);
if (myInter)
myInter->executeMethod(methodKey);
Looks like a good case for a Mediator Pattern.
This pattern manage communication between 2 objects that he owns.