I have a situation like
Shape *shape =dynamic_cast<Shape*>(obj);
if(dynamic_cast<Rectangle*>(obj))
{
func();
Rectangle* obj1 = dynamic_cast<Rectangle*>(obj);
obj1->DoSomething1();
obj1->DoSomething2();
}
else if(dynamic_cast<Circle*>(obj))
{
func();
Cirlce* obj2 = dynamic_cast<Cirlce*>(obj);
obj1->DoSomething3();
obj1->DoSomething4();
}
else if(dynamic_cast<Blah*>(obj))
{
func();
Blah* obj1 = dynamic_cast<Blah*>(obj);
obj1->DoSomething5();
obj1->DoSomething6();
}
...
...
What is the best approach for avoiding calling the dynamic_cast again inside a if/else statement and execute a method for that particular object type?
In general, you should avoid such constructs and utilitize polymorphism the way it was intended to be used, eg:
class Shape
{
public:
virtual void DoSomething() = 0;
};
class Rectangle : public Shape
{
public:
void DoSomething()
{
DoSomething1();
DoSomething2();
}
};
class Circle : public Shape
{
public:
void DoSomething()
{
DoSomething3();
DoSomething4();
}
};
class Blah : public Shape
{
public:
void DoSomething()
{
DoSomething5();
DoSomething6();
}
};
Shape *shape = dynamic_cast<Shape*>(obj);
if (shape)
{
func();
shape->DoSomething();
}
If that is not an option for your code, you can do the following to remove the duplicate dynamic_cast calls, at least:
if (Rectangle *r = dynamic_cast<Rectangle*>(obj))
{
func();
r->DoSomething();
}
else if (Circle *c = dynamic_cast<Circle*>(obj))
{
func();
c->DoSomethingElse();
}
else if (Blah *b = dynamic_cast<Blah*>(obj))
{
func();
b->DoSomethingElseElse();
}
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 one base B and its 2 derived (D1, D2) classes that look like this
struct B
{
virtual B* DoSomething()=0;
};
struct D1:public B
{
B* DoSomething()
{
// D1 does something
return pD1;
}
};
struct D2:public B
{
B* DoSomething()
{
// D2 does something
return pD2;
}
};
and now I have a function
void Init(B*pB)
{
if(pB is D1)
{
D1* pD1=down_cast(pB);
pD1->MethodD1();
}
else if(pB is D2)
{
D2* pD2=down_cast(pB);
pD2->MethodD2();
}
else
{
//do something else
}
}
I don't want to check types in Init() method like this but don't know what else I can do.
really you should be doing
struct B
{
virtual void Init();
virtual B* DoSomething()=0;
};
struct D1:public B
{
B* DoSomething()
{
// D1 does something
return pD1;
}
void Init()
{
MethodD1();
}
};
struct D2:public B
{
B* DoSomething()
{
// D2 does something
return pD2;
}
void Init()
{
MethodD2();
}
};
and in your main code
void Init(B*pB)
{
pB->Init();
}
thats the whole point of encapsulation, inheritance, virtual methods, etc.
Here is your Init() method not in pseudo code:
void Init(B*pB)
{
if(D1 *pD1 = dynamic_cast<D1*>(pB))
{
pD1->MethodD1();
}
else if(D2 *pD2 = dynamic_cast<D2*>(pB))
{
pD2->MethodD2();
}
else
{
//do something else
}
}
As you can see dynamic_cast return nullptr if the type of the derived class is not the one you are casting for.
You can do this also using references, in that case dynamic_cast returns an exception if the type is not the one you are casting, so, since exception handling is not free it's always better to use pointers for dynamic cast purpose.
Please note also that this is a runtime check, not a compile time check.
I'm working on a small game in my free time and while coding it I came across an issue.
I've isolated the issue and made it as small as possible here:
#include <iostream>
#include <memory>
#include <vector>
#include <Windows.h>
class Base
{
public:
std::string p;
virtual ~Base()
{
}
virtual std::vector<std::shared_ptr<std::string>> getText() = 0;
};
class Derived1 : public Base
{
public:
Derived1()
{
p = "from1";
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{std::shared_ptr<std::string>(&p)};
}
};
class Derived2 : public Base
{
public:
Derived2()
{
p = "from2";
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{std::shared_ptr<std::string>(&p)};
}
};
int main()
{
std::unique_ptr<Base> state;
std::vector<std::shared_ptr<std::string>> displayText;
state.reset(new Derived1());
displayText = state->getText();
while(1)
{
for(auto i = displayText.begin(); i != displayText.end(); ++i)
std::cout << **i;
if (GetKeyState('2') < 0)
{
state.reset(new Derived2());
displayText.clear();
displayText = state->getText();
}
else if (GetKeyState('1') < 0)
{
state.reset(new Derived1());
displayText.clear();
displayText = state->getText();
}
}
return 0;
}
When pressing "1" and "2" back and forth it seems to work sometimes, and when I exit out I get something like -1073741510 or similar as the return value. In my game code it also seems to crash a lot.
(By exit out I mean using the X button on the command window, sorry for not clarifying)
After doing some research on unique_ptr and pointers in general along with polymorphic classes I still can't understand why this behaves the way it does.
So, what's going on here?
You are creating a shared_ptr from a stack variable. This will end up calling delete on p which is not safe. See Calling delete on variable allocated on the stack
EDIT:
You would need to make p a pointer. You could do something like the following:
class Base
{
public:
std::shared_ptr<std::string> p;
virtual ~Base()
{
}
virtual std::vector<std::shared_ptr<std::string>> getText() = 0;
};
class Derived1 : public Base
{
public:
Derived1()
{
p = std::make_shared<std::string>("from1");
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{p};
}
};
class Derived2 : public Base
{
public:
Derived2()
{
p = std::make_shared<std::string>("from2");
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{p};
}
};
I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?
Is there a way to use a static pointer so that I have a member
static **int m_switch;
and do something like
m_switch = condition ? &m_b : &m_c;
and call
*m_switch->doStuff();
Does the compiler here also replace the extra pointer hop because it is a static?
Is there any other smart way to do those switches?
Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.
Since you want to emulate this, you can start by making the interface:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
And then you make a template wrapper:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
You need to have both members implement a common interface to use them similarly. But in order to do that, you need to define the interface and relay the calls to the B and C classes.
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
But typing this up made me realize that defining D and E could get really tiresome and against what you're trying to save. However, you can define a template to create them like #paddy has done.
There's no one-size-fits-all solution for your problem. What to use depends on your particular problem. A few possible answers:
Interfaces
Strategy Pattern
Pointers (to hold a function or class which implements doStuff)
An interface is like a contract. Any class which inherits from the interface must implement its members. For instance,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
Can now be used by other classes:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
And now, in general, one may do:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
This can be used in your particular use case as follows:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
First you must change your memebr variables m_b and m_c to std::shared_ptr.
Add a member variable of type std::function(void()) to hold the target function you want to call. In your sample it is do_stuf.
In your setter functions you can bind target function to your std::function and in do_stuf just call std::function.
(You need a C++11 compiler)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}
I have a set of classes like this:
class A {
public:
int DoIt() {
//common code
}
};
class B : public A {
int DoIt() {
if (A::DoIt() == 1) {
return 1;
}
else {
// do b specific code
}
}
};
class C : public A {
int DoIt() {
if(A::DoIt()==1) {
return 1;
}
else {
// do c specific code
}
}
};
Is there a way I can avoid manually putting this code:
if (A::Doit() == 1) { return 1; } else {
in every class which is derived from A?
Just separate the specific code to another method virtual method.
class A
{
public:
int DoIt() /*final*/
{
// common code
if (return_value == 1)
return 1;
else
return DoIt_specific();
}
private:
virtual int DoIt_specific() = 0;
// ^ or some "A"-specific actions if A cannot be abstract.
};
class B : public A
{
virtual int DoIt_specific() /*override*/
{
// specific code for B
}
};
This is known as the non-virtual interface idiom.