0

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();

Amirsaman
  • 181
  • 1
  • 5
  • 8
    I think what you need is to have both `A` and `B` derive from a common base class `C` with pure virtual `f()`, but it's hard to tell for sure. – Steve Townsend Mar 11 '13 at 18:44

3 Answers3

1

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);
}
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Thanks! This actually works perfectly on C++! The final code that I am trying to use this procedure is actually using CUDA. Is there any libraries similar to boost that might work on CUDA as well? – Amirsaman Mar 12 '13 at 20:18
  • Thanks a lot @Andy :) For the record, in CUDA, it is giving me: `error : expected an identifier` – Amirsaman Mar 12 '13 at 20:29
1

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().

WormholeWizard
  • 366
  • 1
  • 3
  • Thanks a lot for your clear response. I tried it, it is giving me lots of warnings which makes sense: `function "Base::D_w()" is hidden by "Set_Coefficients_UW::D_w" -- virtual function override intended?` But it is also giving me this error: `error : object of abstract class type "Set_Coefficients_UW" is not allowed: 1> pure virtual function "Base::D_w" has no overrider` – Amirsaman Mar 11 '13 at 23:36
  • As suggested at comments to your question, your situation in not so simple, as you described. Function D_w of class Set_Coefficients_UW probably has declaration that differs from that of function D_w() of Base class, am I right? So it only hides base function, not overrides it. But base function is declared as "pure virtual" and need overriding in inheriting classes, cause it has no definition yet. If you want functions of classes A and B have different arguments, you probably should really look toward boost library or rethink design of program. – WormholeWizard Mar 12 '13 at 10:21
  • Thanks a lot for your advice @WormholeWizard, boost actually worked in C++!! But I wasn't able to use it in CUDA device kernels, my final destination. – Amirsaman Mar 12 '13 at 20:32
  • For the record, I managed to work it out using the method presented here: [C++ Factory Pattern](http://login2win.blogspot.ca/2008/05/c-factory-pattern.html) but it runs extremely slow!!! – Amirsaman Mar 14 '13 at 23:03
0

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).

Community
  • 1
  • 1
user1952500
  • 6,611
  • 3
  • 24
  • 37