#include <iostream>
class EquationOfMotion
{
public:
// other attributes
virtual void findNextTimeStep() = 0;
};
class SystemModel
{
public:
EquationOfMotion* p_eom;
// other atributes
SystemModel(EquationOfMotion* new_p_eom)
{
p_eom = new_p_eom;
}
};
class VehicleEquationOfMotion: public EquationOfMotion
{
public:
VehicleEquationOfMotion(...){/* initialise attribute*/}
virtual void findNextTimeStep(){}
};
class Vehicle: public SystemModel
{
// ???? Implementation ?????
}
Vehicle is a specialization of SystemModel where p_eom points to VehicleEquationOfMotion.
I would like to initialise, an instance of VehicleEquationOfMotion and point to it p_eom in Vehicle. I want it to be defined only within the scope of Vehicle, and at the same time, not to use heap.
Is it even possible to reside VehicleEquationOfMotion object inside Vehicle without using the heap? (If not, please suggest where the design has gone wrong).
Might be helpful: I thought about the implementation in this question but ran into trouble (see the question).
If I got your question correctly, then do it like this:
class FooChild : public FooParent
{
public:
FooChild (int pX):m_BarChild(pX), FooParent(&m_BarChild) // point p_barPar to instance of BarChild (i.e. m_BarChild)
{
}
private:
BarChild m_BarChild; // instance of BarChild resided in the stack(not the heap) and is local to FooChild
}
If you want to have FooParent.p_barPar to be pointing to a BarChild that resides inside FooChild, you might need to add a default ctor to FooParent and a method as follows as well: set_p_barPar(BarChild* new_p_bar){p_barPar = new_p_bar;}. So you get:
class FooParent
{
public:
BarParent* p_barPar;
FooParent (){}
FooParent (BarChild* new_p_bar)
{
p_barPar = new_p_bar;
std::cout << p_barPar->x << std::endl;
}
protected:
set_p_barPar(BarChild* new_p_bar)
{
p_barPar = new_p_bar;
}
}
Then you can implement FooChild:
class FooChild : public FooParent
{
public:
FooChild(int new_x, BarChild* new_p_bar):_bar_child(new_x)
{
set_p_barPar(&_bar_child);
}
private: //? Depends on your plans
BarChild _bar_child();
}
Use a class template.
class EquationOfMotion { ... };
template <typename EOM>
class SystemDynamics
{
EOM EquationOfMotion;
...
};
class VehicleEquationOfMotion : public EquationOfMotion { ... };
class Vehicle : public SystemDynamics<VehicleEquationOfMotion> { ... };
May be this is what you want. But the design is not safe. You are passing the pointer to a uninitialized object.
class Vehicle: public SystemModel
{
public:
Vehicle(): SystemModel(&_vem)
{
}
VehicleEquationOfMotion _vem;
}
However, it is safer to do the following:
class SystemModel
{
public:
EquationOfMotion* p_eom;
// other atributes
SystemModel()
{
}
};
class Vehicle: public SystemModel
{
public:
Vehicle(): SystemModel(&_vem)
{
p_eom = &_vem;
}
VehicleEquationOfMotion _vem;
};
Related
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;
}
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);
}
I am implementing a decorator pattern following the example in here:
Class I: is the interface class, common to both core class and decorator base class
Class A: is the core class
Class D: is the decorator base class
Classes X, Y, Z: inherit from the decorator base class and extend functionality of the core class dynamically
There is one method in class A (A::endTraining()), which is triggered at the end of a timer variable (also present in class A). This method needs to call some member of X, Y and Z classes.
Is it possible? Is it good practice? How?
For example, is creating a mechanism to register the pointers-to-XYZ::endTraining in class A a correct approach?
(showing only relevant bits)
typedef void (D::*pCallback_fn)(void);
class I
{
public:
virtual void endTraining() = 0;
virtual void regTrainingCallbacks(pCallback_fn ptrFn) = 0;
};
class A: public I {
public:
void endTraining() {
//do stuff
//then do stuff in D (and its derivatives)
// by iterating through fnList
}
void regTrainingCallbacks(pCallback_fn ptrFn)
{
fnList.push_back( ptrFn );
}
private:
std::list<pCallback_fn> fnList;
};
class D: public I {
public:
D(I *inner) {
m_wrappee = inner;
}
void regTrainingCallbacks(pCallback_fn ptrFn)
{
m_wrappee->regTrainingCallbacks(ptrFn);
}
private:
I *m_wrappee;
};
class X /*,Y,Z*/ : public D {
public:
X(I *core): D(core)
{
D::regTrainingCallbacks( this->*endTraining() ); //
}
private:
void endTraining(){
//do stuff when called by A::endTraining() through D
}
};
What can be done instead?
Addressing one fault in the original design, in which the 'trainer' (the entity registering training callbacks) must be a callback in itself (is there any reason the notifier - former class A - must be a callback itself?).
I changed the class names to put into evidence their responsibilities.
The MainTrainingProcess replaces the original class A (instances of which would have been wrapped by D-es) and the D itself.
class EndTrainingListener
{
public:
virtual ~EndTrainingListener() { }
virtual void endTraining()=0;
};
class ITrainingProcess
{
public:
virtual ~ITrainingProcess() { }
virtual void regTrainingCallbacks(EndTrainingListener* callback) = 0;
};
class MainTrainingProcess : public ITrainingProcess {
public:
virtual ~MainTrainingProcess() {
// destroy other resources used during training
}
virtual void regTrainingCallbacks(EndTrainingListener* callback) {
this->listeners.push_back(callback);
}
void train() {
// do training stuff
// ...
// do my specific actions at the end of training
// ...
// finish by notifying all listeners
this->atEndTraining();
}
protected:
void atEndTraining() {
for(auto l : this->listeners) {
l->endTraining();
}
}
std::list<EndTrainingListener*> listeners;
};
class X /*Y, Z*/ : public EndTrainingListener {
public:
virtual ~X();
virtual void endTraining() {
// do specific stuff
}
};
I've recently received a very good answer as how to overload specific class members by deriving classes.
The issue now is that one of the members is in fact templated with specializations either being BaseClass, DerivedClass or Derived2Class
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
template<class T>
class Queue
{
public:
Queue();
Queue(T*);
}
class Com
{
public:
virtual void setReady()
{
cout << "Com" << endl;
}
};
class DerivedCom : public Com
{
public:
void setReady()
{
cout << "DCom" << endl;
}
};
class Derived2Com : public Com
{
public:
void setReady()
{
cout << "D2Com" << endl;
}
};
class BaseClass
{
protected:
Com* com;
Queue<BaseClass>* queue;
public:
BaseClass(Com* c = new Com, Queue<BaseClass>* q = new Queue<BaseClass>) : com(c), queue(q)
{
}
void setReady()
{
com->setReady();
}
};
class DerivedClass : public BaseClass
{
public:
DerivedClass() : BaseClass(new DerivedCom, new Queue<DerivedClass>)
{
}
};
class Derived2Class : public BaseClass
{
public:
Derived2Class() : BaseClass(new Derived2Com, new Queue<Derived2Class>)
{}
};
int main()
{
BaseClass* base = new Derived2Class();
base->setReady();
return 0;
}
I can, without problem, "overload" simple classes like Com, DerivedCom and Derived2Com but the constructor signature of BaseClass won't fit to the type the deriving classes are trying to send it.
Instead of Queue<BaseClass>* queue; you should have Queue<BaseClass*> queue; or, even better, Queue<std::unique_ptr<BaseClass>> and initialize it only in the base constructor:
BaseClass(Com* c = new Com, Queue<BaseClass*> q = Queue<BaseClass*>()) : com(c), queue(q)
{
}
However having the BaseClass hold a collection of itself as a member is a code smell. I'd re-think that part.
The reason it's not working is that Queue<BaseClass> and Queue<DerivedClass> are completely different classes.
You should actually have Queue<BaseClass*>* queue = new Queue<BaseClass*>(); This declares a Queue pointer of type BaseClass pointer on the heap and allows you to use the pointer notation you mentioned above as queue->push(&BaseClass::setReady); and such...
Following an answer found elsewhere I changed the concept of class Queue to be template-less.
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.