convert class A to class B without modifying A

Jan 19, 2010 at 4:57am
hello all,
I would really appreciate some guidance in a problem im in, and im sure one of you will know how to help :)
first, lets say i have class A and class B and function f:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A
{
public:
   int int_a;
};
class B
{
public:
   int int_b;
};
void f(B bb)
{
   std::cout << "int_b value from class B is: " << bb.int_b << "\n";
}
int main(int argc, char* argv[])
{
   A aa;
   aa.int_a = 123;
   f(aa);
}

so im confused as to what operator method should be used when f() will try to convert aa to class B. The annoying part is that i cannot touch the code of class A, so using "operator B()" in class A is not possible. Also, as I am actually making a wrapper class, i would _really_ like to not have to change the "f(aa);" call. (ie, without using "f((B)aa);"

Is anyone able to help? Or anything i should clarify?
Jan 19, 2010 at 5:43am
can you change B?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A
{
public:
   int int_a;
};
class B
{
public:
  B(const A& a) : int_b(a.int_a) { }   // <- make a ctor
   int int_b;
};
void f(B bb)
{
   std::cout << "int_b value from class B is: " << bb.int_b << "\n";
}
int main(int argc, char* argv[])
{
   A aa;
   aa.int_a = 123;
   f(aa);  // <- now this works.
}
Jan 19, 2010 at 7:38am
Jan 19, 2010 at 7:51am
thanks for the reply, but no i cant change B, sorry. however, i achieved a solution with constructors taking a B object. although, ive updated what i need done:
instead of casting a B object, i need to cast a B* to a A*, but the compiler can never find a conversion method :S ill add more info later

EDIT:
oops, sorry! I meant you cannot change class A but you can change class B. My apologies, thanks for the assistance, but I now need to convert A* to B*. (not B* to A*, I'm very sorry I had my classes mixed round the wrong way!)
Last edited on Jan 19, 2010 at 1:43pm
Jan 19, 2010 at 8:39am
You need an adapter.
Jan 19, 2010 at 10:25am
Well if u don't want to change anything in any one of the class, then u can derive class A and B from a same class let's say parent class and write an virtual function which has to be over ridden by the derived classes.
And in the main, you can create an parent object referring to anyone of the derived class:

Sample code be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Parent
{
public:
	Parent(){};
	virtual void f()
	{
		cout<<"Hi";
	}
};

class A:public Parent
{
public:
   int int_a;
   A():Parent()
   {
	   int_a = 10;
   }
   void f()
   {
	   cout<<"A integer is:"<<int_a;
   }

};
class B:public Parent
{
public:
   int int_b;
   B():Parent()
   {
	   int_b=120;
   }
   void f()
   {
	   cout<<"B integer is:"<<int_b;
   }
};


int main(int argc, _TCHAR* argv[])
{
	Parent* p = new A();
	p->f();//will call specific member function of the class
	
  
	return 0;
}
Jan 19, 2010 at 10:51am
If A's destructor isn't virtual, you can't destroy it properly.

You need to use aggregation not inheritance.
Jan 19, 2010 at 1:29pm
Kbw: what is an adapter and could you explain aggregation please?
Somshekhar: you can change class B but not A (A in my program is a MFC CObjList, my custom class (B)is a wrapper to replace the MFC with a std::vector) but u can't change the inheritance of B sorry.

So if f() needs a pointer to a B object (ie. "f(B*pObjB){}" ) and the function call looks like "f(&aa);" how could I convert the pointer to an A class to a pointer to a B class?
Thanks for all your help so far!
Last edited on Jan 19, 2010 at 1:34pm
Jan 19, 2010 at 1:49pm
sample code I would like to get working:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A
{
public:
   int int_a;
};
class B
{
public:
   int int_b;
   //some user-defined conversion/casting method from *A to *B
};
void f(B* bb)
{
   std::cout << "int_b value from class B is: " << bb->int_b << "\n";
}
int main(int argc, char* argv[])
{
   A aa;
   aa.int_a = 123;
   f(&aa);
}

Jan 19, 2010 at 3:53pm
How is this different from your original post? My code still applies. Give B a ctor that takes an A.

The only hitch is that f() shouldn't take a pointer, but should take a const reference:

1
2
3
4
5
6
7
8
9
10
11
12
/*  A and B same as post above */

void f(const B& bb)  // <- const reference
{
   std::cout << "int_b value from class B is: " << bb.int_b << "\n";
}
int main(int argc, char* argv[])
{
   A aa;
   aa.int_a = 123;
   f(aa);  // <- this works fine
}



EDIT:

Oh wait... you need to cast the pointer.

You can't. Closest you could do is have B dynamically allocate an instance of itself with an A object.... but then you have to delete it afterwards. This is how you could do it, but I really don't advise this approach:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class B
{
public:
   int int_b;

   static B* Create(const A* a)
   {
      B* b = new B;
      b->int_b = a->int_a;
      return b;
   }
};

int main()
{
   A aa;
   aa.int_a = 123;

   B* b = B::Create(&aa);
   f(b);
   delete b;
}


Again -- this solution is poor. You're much better off with the const reference as above.
Last edited on Jan 19, 2010 at 4:00pm
Jan 19, 2010 at 4:36pm
this is from the tutorial on type casting

static_cast can perform conversions between pointers to related classes, not only from the derived class to its base, but also from a base class to its derived. This ensures that at least the classes are compatible if the proper object is converted, but no safety check is performed during runtime to check if the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe. On the other side, the overhead of the type-safety checks of dynamic_cast is avoided.

1
2
3
4
class CBase {};
class CDerived: public CBase {};
CBase * a = new CBase;
CDerived * b = static_cast<CDerived*>(a);

This would be valid, although b would point to an incomplete object of the class and could lead to runtime errors if dereferenced.

static_cast can also be used to perform any other non-pointer conversion that could also be performed implicitly, like for example standard conversion between fundamental types:

1
2
double d=3.14159265;
int i = static_cast<int>(d);

Or any conversion between classes with explicit constructors or operator functions as described in "implicit conversions" above.
Jan 19, 2010 at 6:56pm
I just want to make clear:

static casting (or any other type of casting) is NOT AN OPTION unless the two classes are related somehow (as in, one is a parent class of the other).

Since that doesn't seem to be the case in this example, you should not even consider it here.
Last edited on Jan 19, 2010 at 6:56pm
Jan 20, 2010 at 6:26am
thanks guys, although no luck as yet :(
So it is not possible to convert a B* to a A*? (without modifying A)

1
2
3
4
5
6
7
8
9
10
f(A* aa)
{
   std::cout << "Conversion Successfull\n";
}

int main()
{
   B bb;
   f(&bb);
}


Or even converting bb to A* somehow? im sad i cant do this :( i need to leave the function call and A just like the way they were before, because the code im working with is HUGE and to go and change every function call, parameter list and assignments is too big a task to do all at once...
Jan 20, 2010 at 6:31am
argh.. what are you trying to program? i can't understand the point why you wanna do that.
Jan 20, 2010 at 7:05am
Well, if they are exactly the same class (same members, same order, same functions, etc) then I don't see why you don't just use class A instead of converting to it from some other class that is otherwise the same. However, if there are any differences, you can't without using one of the solutions about.

CNoob wrote:
because the code im working with is HUGE and to go and change every function call, parameter list and assignments is too big a task to do all at once...


That sucks...you could try using regular expressions + search/replace. That's what I did when I was trying to clean up messes like that.
Jan 20, 2010 at 7:16am
the program i am working on uses MFC (not mine - the companies). and I need to get rid of any MFC code. So i made a wrapper for a std::vector which works exactly the same as the MFC class CObList (in terms of method names, return values etc).

So, I need to replace the MFC CObList's piece by piece so that I dont do everything at once and find none of it works. here is an example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
main()
{
   MFC::CObList objectlist;
   function_a(&objectlist);   //this (or something similar) is used so many times its not possible to change every time its called
}

function_a(Wrapper::CObList* objlist)   //<-- convert from MFC::CObList* to Wrapper::CObList* on the fly
{
   //do some stuff
   function_b(objlist);
}

function_b(MFC::CObList* objlist)   //<-- convert from Wrapper::CObList* to MFC::CObList* on the fly
{
   //do some stuff
}

calling functions with pointers is the main way the functions are called (hence the reason i wanted to convert a MFC::CObList* to a Wrapper::CObList*). Well thats the reason, although its probably quite hard to understand, just ask for clarification or anything!

classes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace MFC
{
   class CObList
   {
        //Not editable
        //Methods and variables etc are here
   }
}

namespace Wrapper
{
   class CObList
   {
       //Editable - What operators/constructors etc to use?
       //Methods and stuff are here
   }
}
Last edited on Jan 20, 2010 at 7:17am
Topic archived. No new replies allowed.