What is a better way to implement this in C++ (without if-else). In C I can initialize function pointer, and then just call function pointers. So if you look at class C, some objects of class C use only class A and some class B. I am more familiar with C than C++.
class A {
public:
int func1();
int func2();
int func3();
};
class B:A {
public:
int func1() {x=1; A::func1();}
int func2() {A::func2(); x=1;}
int func3() {x=1; A::func2();}
};
class C {
public:
C::C(bool class_a) {_class_a = _class_a;}
void func_c_1()
{
if(_class_a) a.func1();
else b.func1();
}
void func_c_2()
{
if(_class_a) a.func2();
else b.func2();
}
void func_c_3()
{
if(_class_a) a.func3();
else b.func3();
}
private:
bool _class_a;
A a;
B b;
};
Your code doesn't compile and I could be misunderstanding you completely but if you want a class which does different stuff depending on how it was created you might be helped by using a virtual base with pure virtual functions and deriving A and B from it overriding those virtual functions.
class Base
{
public:
virtual int func1() = 0;
virtual int func2() = 0;
virtual int func3() = 0;
virtual ~Base(){} //it is important that this is virtual
};
class A: public Base
{
public:
virtual int func1(){
//do something
}
virtual int func2(){
//do something
}
virtual int func3(){
//do something
}
};
class B: public A
{
public:
virtual int func1(){
//do something else
((A*)this)->func1(); //call A's func1()
}
virtual int func2(){
//do something else
}
virtual int func3(){
//do something else
}
};
Base *a = new A;
Base *b = new B;
Base *c = a;
c->func1(); //does something
c=b;
c->func1(); //does something else
Otherwise if you essentially want two different classes (with distinct types) you could use a template. If this is what you want comment and I will add example code.
It also should be noted that nothing is stopping you from using function pointers in C++ although I wouldn't recommend it. Here is an example code just for giggles:
#include <functional>
class A
{
public:
int func1(){
//do something
return 1;
}
int func2(){
//do something
return 1;
}
int func3(){
//do something
return 1;
}
};
class B
{
public:
int func1(){
//do something else
return 1;
}
int func2(){
//do something else
return 1;
}
int func3(){
//do something else
return 1;
}
};
class C
{
public:
C(bool useA)
{
if(useA) {
func1 = std::bind(&A::func1,a_);
func2 = std::bind(&A::func2,a_);
func3 = std::bind(&A::func3,a_);
}
else {
func1 = std::bind(&B::func1,b_);
func2 = std::bind(&B::func2,b_);
func3 = std::bind(&B::func3,b_);
}
}
std::function<int()> func1;
std::function<int()> func2;
std::function<int()> func3;
private:
A a_;
B b_;
};
C c(true);
C c2(false);
c.func1();
It looks to me like you're trying to understand inheritance in C++. Your code looks like it's trying to get different behavior depending on if you tell it to be a class A or a class B. If so, this should help:
#include <iostream>
using namespace std;
class A
{
public:
void foo() { cout << "A::foo\n"; }
void bar() { cout << "A::bar\n"; }
};
class B : public A
{
public:
void foo() { cout << "B::foo\n"; }
void fee() { cout << "B::fee\n"; }
};
main()
{
A* a = new A();
B* b = new B();
a->foo();
a->bar();
b->foo();
b->bar();
b->fee();
((a)b)->foo();
((a)b)->bar();
}
I make class A, and (publicly) make class B inherit from it. Within main, the first 5 lines show behavior you'd expect, but if you want the b object to act as an A, I just cast it to it, and it does. (If you run this code, you'll see that the final foo line emits A::foo.)
So the behavior is not forced at construction time. When you construct the object, B::foo overrides A::foo. But simply by casting to the superclass, you can access the original functions.
Note, if you want b.foo() to always emit "B::foo", set the foo function in A to virtual:
class A
{
public:
virtual void foo() { cout << "A::foo\n"; }
void bar() { cout << "A::bar\n"; }
virtual ~foo() { /* any destructor code for the base class */ }
};
In this case, whether you use b->foo() or ((A*)b)->foo(), the output will be "B::foo". The run time will work with the original type of the object, instead of with the type you cast it to. Important - As soon as you make any virtual function in your class, you must make a virtual destructor for that function. If you don't, only the base class's destructor will be called when your object is deleted. (When you use virtual destructors, each destructor is called from the most-derived class to the base, essentially unwinding the work that was done when the object was constructed.)
Hope this helps...
Related
Consider this trivial C++11 inheritance example:
class A
{
public:
virtual void func() = 0;
};
class B : public A
{
public:
void func() { func1(); /* Wish this could be func1() or func2()! */ };
void func1() { /* Does one thing */ };
void func2() { /* Does another thing */ };
};
void doSomeStuff(A &a)
{
a.func();
}
int main()
{
B b;
doSomeStuff(b);
return 0;
}
I'm trying to make it so that I don't have to modify (or duplicate) class A's definition or the function doSomeStuff, but I want the invocation of a.func() to call either func1() or func2() of B. Ideally I'd change the line doSomeStuff(b) to something like doSomeStuff(b.butWithFunc1) but I'd also be OK with some way to modify B's version of func() so that it can make the decision internally to call func1 or func2 based on some parameter.
The same object of type B may have to sometimes call func1 or func2 during an invocation of func, so I can't use a persistent member of class B to decide. Adding a parameter to func() would make this trivial as well, but that's not something I can do either.
I'm kind of wondering if there's some way to add to class B a function that returns a mutated version of class B which calls func2() from func(), or if I can play some tricks with function pointers or something. However, something tells me I'm Doing It Wrong and the obvious solution is staring me in the face.
If it helps for context, class A is similar to a std::lock_guard, and it works fine for things like semaphores and mutexes (for which there is only one definition of lock and unlock), but class B in this example is a R/W lock - so there's a "readLock" and "writeLock", and I'd like to be able to say something like "auto lock this RW lock as a read lock" without having to duplicate/break the auto lock code.
For instance:
{
A_AutoSem(myMutex); // calls lock() on myMutex
//... do some stuff
// end of the block, ~A_AutoSem calls unlock on myMutex
}
{
A_AutoSem(B_RWLock); // how do I say here "call readLock"?
// ... do some stuff
// end of the block ~A_AutoSem should call "readUnlock" on B_RWLock
}
Simply define some additional classes to call func1() and func2(), and then pass those classes to doSomeStuff() instead of passing B directly.
Try something like this:
class A
{
public:
virtual void func() = 0;
};
class B
{
public:
void func1() { /* Does one thing */ };
void func2() { /* Does another thing */ };
};
class C1 : public A
{
private:
B &m_b;
public:
C1(B &b) : m_b(b) {}
void func() override { m_b.func1(); }
};
class C2 : public A
{
private:
B &m_b;
public:
C2(B &b) : m_b(b) {}
void func() override { m_b.func2(); }
};
void doSomeStuff(A &a)
{
a.func();
}
int main()
{
B b;
{
C1 c(b);
doSomeStuff(c);
}
{
C2 c(b);
doSomeStuff(c);
}
return 0;
}
Live Demo
Alternatively:
class A
{
public:
virtual void func() = 0;
};
class B
{
private:
void func1() { /* Does one thing */ };
void func2() { /* Does another thing */ };
public:
class C1 : public A
{
private:
B &m_b;
public:
C1(B &b) : m_b(b) {}
void func() override { m_b.func1(); }
};
class C2 : public A
{
private:
B &m_b;
public:
C2(B &b) : m_b(b) {}
void func() override { m_b.func2(); }
};
};
void doSomeStuff(A &a)
{
a.func();
}
int main()
{
B b;
{
B::C1 c(b);
doSomeStuff(c);
}
{
B::C2 c(b);
doSomeStuff(c);
}
return 0;
}
Live Demo
This question already has answers here:
Force all classes to implement / override a 'pure virtual' method in multi-level inheritance hierarchy
(5 answers)
Closed 5 years ago.
Consider this:
struct Base {
virtual void fn() = 0;
};
struct A: Base {
virtual void fn();
};
struct B: A {
// fn is not overridden here
};
Basically, fn is implemented in A. B derives from A, and B doesn't override fn.
I'd like to have technique to make B must override fn, because it is an error, if it is not overridden.
Is is possible to do this? A compile-time error (or maybe warning) would be the best, but if it is not possible, then a runtime error is OK too. I'd just like to know, if someone forgets to override fn in a derived class.
The reason for this? fn could return class-related information. For example, it could return the class name. Or it could return the amount of allocated space the object uses (for debug purposes). Or do some class-related task (for example, loading/saving its state).
You cannot force the compiler to generate an error if fn is not overridden in B.
You can modify your code a little bit to get what you want.
Make A::fn a pure-virtual. Leave the implementation as is in A. Remember that it's perfectly OK to implement A::fn even when it is declared pure-virtual.
That will force you to override fn in B. The implementation of B::fn can utilize as much of A::fn as it needs to.
truct Base {
virtual void fn() = 0;
};
struct A : Base {
virtual void fn() = 0;
};
void A::fn()
{
// Add implmentation details
}
struct B : A {
// fn must be overridden here
virtual void fn();
};
void B::fn()
{
A::fn();
// Add additonal logic for B
}
You can generate run time error though if A::fn is called an on B object.
Here's one way to do it.
#include <iostream>
struct Base
{
virtual void fn() = 0;
virtual int getTypeID() = 0;
protected:
static int getNextID()
{
static int nextid = 0;
return ++nextid;
}
static int getClassTypeID()
{
static int id = getNextID();
return id;
}
};
struct A : Base
{
virtual void fn();
virtual int getTypeID()
{
return getClassTypeID();
}
private:
static int getClassTypeID()
{
static int id = getNextID();
return id;
}
};
void A::fn()
{
if ( this->getTypeID() != A::getClassTypeID() )
{
// Problem.
std::cout << "ERROR. fn() called on a derived class object.\n";
}
else
{
std::cout << "OK. fn() called on an A object.\n";
}
}
struct B : A
{
virtual int getTypeID()
{
return getClassTypeID();
}
static int getClassTypeID()
{
static int id = getNextID();
return id;
}
};
int main()
{
A* a1Ptr = new A;
A* a2Ptr = new B;
a1Ptr->fn();
a2Ptr->fn();
}
Output:
OK. fn() called on an A object.
ERROR. fn() called on a derived class object.
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();
}
If I have two classes:
class A{
f();
}
class B{
f();
};
I need to assign one of these classes to an object based on a condition like:
define variable
if condition1
variable = A
else
variable = B
and then I would use the assigned variable.f();
You should look toward inheritance and virtual functions.
Code might look like
class Base
{
virtual void f() = 0;
};
class A : public Base
{
virtual void f()
{
//class A realization of f
}
};
class B : public Base
{
virtual void f()
{
//class B realization of f
}
};
And then you can do this
Base* VARIABLE = 0;
if (*condition*)
{
VARIABLE = new A();
}
else
{
VARIABLE = new B();
}
VARIABLE->f();
But it not always a good idea to use inheritance and virtual functions. Your classes A and B should have something in common, at least the meaning of function f().
Provided A and B are meant to be unrelated types (i.e. not part of an inheritance hierarchy), you could use Boost.Variant in combination with the boost::static_visitor<> class to achieve something similar:
#include <boost/variant.hpp>
#include <iostream>
struct A { void f() { std::cout << "A::f();" << std::endl; } };
struct B { void f() { std::cout << "B::f();" << std::endl; } };
struct f_caller : boost::static_visitor<void>
{
template<typename T>
void operator () (T& t)
{
t.f();
}
};
bool evaluate_condition()
{
// Just an example, some meaningful computation should go here...
return true;
}
int main()
{
boost::variant<A, B> v;
if (evaluate_condition())
{
A a;
v = a;
}
else
{
B b;
v = b;
}
f_caller fc;
v.apply_visitor(fc);
}
What you are doing is known in design patterns as the "Factory Pattern". The above answers cover how it should be implemented. You can get more information at How to implement the factory method pattern in C++ correctly and wiki (http://en.wikipedia.org/wiki/Factory_method_pattern).
Here is the code which causes a problem:
class Base
{
public:
virtual void fun()
{
cout<<"Base";
}
};
class Der:public Base
{
Base &pb;
public:
Der(Base&b):pb(b){}
virtual void fun()
{
cout<<"Der...";
pb.fun();
}
};
int main()
{
Der(Der(Base())).fun();
return 0;
}
Run this code,and the result shows "Der...Base..."! This is so amazing, I can't figure it out why the result is not "Der...Der...Base" which is logically right?!
Then I replace the member in class Der Base&pb with Base*pb and change the code into legal, finnaly the output is right which is "Der...Der...Base"!
I debug the code and find that when I use Base&pb, the constructor of Der only ran once while use Base*pb, the constructor ran twice correctly!
Any one who can explain to me what had happened and why?
In Der(Der(Base())).fun() expression the inner Der(Base()) yields an rvalue - the compiler optimizes the code by using copy elision and removes unnecessary copying of objects.
In addition to the #icepack's answer and the following discussion in the comments (summary: the code Der(der) is a cast, which may or may not be realized using constructor; in your case it's not), a workaround for you: you should make your intention clear by not using the constructor.
I would rewrite your code into something like this:
class Base
{
public:
virtual void fun()
{
cout<<"Base";
}
};
class Der:public Base
{
Base &pb;
Der(Base& b) : pb(b) {}
public:
static Der Decorate(Base&& b){ return Der(b); }
virtual void fun()
{
cout<<"Der...";
pb.fun();
}
};
int main()
{
Der::Decorate(Der::Decorate(Base())).fun();
return 0;
}
(outputs: Der...Der...Base).
Changing the code to accept the pointer is easy:
class Base
{
public:
virtual void fun()
{
cout << "Base";
}
};
class Der : public Base
{
Base* pb;
Der(Base* b) : pb(b) {}
public:
static Der Decorate(Base* b){ return Der(b); }
virtual void fun()
{
cout << "Der...";
pb->fun();
}
};
int main()
{
Der::Decorate(&Der::Decorate(&Base())).fun();
return 0;
}