Page 1 of 1

C++ Class Constructor

Posted: Fri Mar 18, 2011 12:30 pm
by Wolftein
Hi!, i want to know if this is posible or there is a cleaner way to do it.

Code: Select all

ClassA myA;

((ClassB*)(&myA))(...);

can i convert ClassA to ClassB (ClassB : public ClassA)? without using new, and RTTI (typecast)


Re: C++ Class Constructor

Posted: Fri Mar 18, 2011 12:45 pm
by neon
Hello,

Typecast does not use RTTI. Is it possible? Of course. Without a typecast? No. Also, in C++ static_cast<> should be used here over a C style cast.

Code: Select all

classA myA;
classB* myB = static_cast<classB*>(myA);

Re: C++ Class Constructor

Posted: Fri Mar 18, 2011 1:17 pm
by Wolftein
neon wrote:Hello,

Typecast does not use RTTI. Is it possible? Of course. Without a typecast? No. Also, in C++ static_cast<> should be used here over a C style cast.

Code: Select all

classA myA;
classB* myB = static_cast<classB*>(myA);
Thanks neon, one last question can i do this?

Code: Select all

ClassA MyClass
#ifdef ...
    ClassB* MyClassChild = (static_cast<ClassB*>(MyClass))(...); // Call Constructor
    MyClass = MyClassChild;
#endif
MyClass.virtualFunction();

Re: C++ Class Constructor

Posted: Fri Mar 18, 2011 2:45 pm
by Tosi
From the code he originally posted it looks like he wants to declare a class of one type but call a constructor of a different class on that one. And I thought my C++ code was ugly...

If I guessed correctly the solution would be to use polymorphism.

Re: C++ Class Constructor

Posted: Fri Mar 18, 2011 10:18 pm
by Wolftein
berkus wrote:One obvious way of doing it is to use placement new.

Code: Select all

ClassA* a = new ClassA;
ClassB* b = new(a) ClassB;
Just be aware if there are storage space changes between ClassA and ClassB (and there certainly might be some, unless you explicitly document, require and assert sizeof(a) == sizeof(b)), then you're screwed.
i can't use new!. Because i want to do that with local variable without dynamic allocation.

This is what i'm trying to do.

Code: Select all

ClassA BaseClass; // ClassA only contains virtual functions
#ifdef _USE_CLASS_B
  // Want to change ClassA to ClassB (ClassB : public ClassA)
#elif   _USE_CLASS_C
  // Want to change ClassA to ClassC (ClassC : public ClassA)
#endif
BaseClass.VirtualFunction(); // Call the function (BaseClass now is ClassB or ClassC, Can't be ClassA becuase all functions are virtual)

Re: C++ Class Constructor

Posted: Sat Mar 19, 2011 12:54 am
by gravaera
Hi,

That's not how polymorphism works...

Code: Select all

user@localhost:/void/cygwin/osdev/zbz$ cat ~/tst.cpp
#include <stdlib.h>
#include <stdio.h>

class animal {
public:
	virtual void foo(void) { printf("animal::foo()"); };
	void bar(void) { printf("animal::bar()"); };
};

class bear
: public animal {
public:
	void foo(void) { printf("bear::foo()"); };
	void bar(void) { printf("bear::bar()"); };
};

/* The purpose of polymorphism (as done in C++) is to allow you to use a
 * pointer or reference to a base class and assign it to an instance of a
 * derived class, and even though the _type_ of the pointer being used may be
 * of the base class, if the object being pointed to is a derived class with an
 * implementation of one of the base class's virtual functions, the _derived_
 * class object's implementation of that function will be called, in spite of
 * type of the pointer being used to refer to the object. Consider:
 **/
animal *pAnim;
bear bearArr[16];

int main(void)
{
	for (int i=0; i<16; i++)
	{
		pAnim = static_cast<animal *>( &bearArr[i] );
		pAnim->foo();
	};
	return EXIT_SUCCESS;
}

user@localhost:/void/cygwin/osdev/zbz$
user@localhost:/void/cygwin/osdev/zbz$ g++ ~/tst.cpp -o ~/tst
user@localhost:/void/cygwin/osdev/zbz$ ~/tst
bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()bear::foo()user@localhost:/void/cygwin/osdev/zbz$ 
Notice how even though the pointer I dereferenced to call foo() was of type "animal", the bear:: implementation of foo() was called. The idea is so you can deal with a list of derived class objects all using one pointer to a base class object, and have all the objects invoke their own internal method, regardless of the pointer used to invoke. The key is that you're casting from a derived class to a base class; not the other way around. Your example:

Code: Select all

ClassA BaseClass; // ClassA only contains virtual functions
#ifdef _USE_CLASS_B
  // Want to change ClassA to ClassB (ClassB : public ClassA)
#elif   _USE_CLASS_C
  // Want to change ClassA to ClassC (ClassC : public ClassA)
#endif
BaseClass.VirtualFunction(); // Call the function (BaseClass now is ClassB or ClassC, Can't be ClassA becuase all functions are virtual)
Takes a base class and tried to cast it to a derived class, and then use polymorphism to do something, though it's not clear what, so it's misdirected on two accounts: your attempt to polymorphism isn't really cogent, and you're casting from a base class to a derived class.

To cast from a base class to a derived class, what you need is "dynamic_cast<>()". Casting up from base to derived has the risk of the class memory space difference causing bugs. Dynamic_cast<> asserts that the two classes are the same size at runtime before casting, so it makes it "safe" to cast upwards. Of course, if dynamic_cast<> determines that there would be a problem casting upwards, it will return an error. Dynamic_cast also requires RTTI, which implies overhead. Bascally, you've probably designed somethign wrong somewhere.

So to answer your original question,
can i convert ClassA to ClassB (ClassB : public ClassA)? without using new, and RTTI (typecast)
No, you can't do it (properly) without RTTI. You can just reinterpret_cast<> and go your way, but whatever result that yields depends on how similar the base and derived classes are in size and layout, and whatever eccentricities your compiler may have in its handling of inheritance. Also, a common mistake people make is to assume that online "tutorials" on C/C++ are as good as a well known, well reputed book (like K&R or Stroustrup): they are not :)

--Have fun
gravaera

Re: C++ Class Constructor

Posted: Sat Mar 19, 2011 2:36 am
by Combuster
As a bit of general advice, if you have to bypass the typing system in any way, your design stinks. Redesign your approach so that using the virtual keyword is sufficient to solve the problem.

Re: C++ Class Constructor

Posted: Tue Mar 22, 2011 8:04 pm
by linuxfood
Have you considered redesigning your "ClassA" to use a delegate?
It appears on the surface to be a good fit for your use case.
However, without providing us with more information, only you can answer that.


OT: Whether or not delegation is idiomatic C++ is something I'm rather curious
about, myself. It's been ages since I last used C++ for anything.

Re: C++ Class Constructor

Posted: Wed Mar 23, 2011 12:43 pm
by linuxfood
berkus wrote:Idiomacy of C++ is fairly orthogonal to the idiomacy of patterns used.
Obviously. However, every language has a "feel" to it, that one would do well to be cultured in.
Certain patterns carry more weight in various communities.

Re: C++ Class Constructor

Posted: Wed Mar 23, 2011 4:22 pm
by JamesM
Wolftein wrote:
berkus wrote:One obvious way of doing it is to use placement new.

Code: Select all

ClassA* a = new ClassA;
ClassB* b = new(a) ClassB;
Just be aware if there are storage space changes between ClassA and ClassB (and there certainly might be some, unless you explicitly document, require and assert sizeof(a) == sizeof(b)), then you're screwed.
i can't use new!. Because i want to do that with local variable without dynamic allocation.

This is what i'm trying to do.

Code: Select all

ClassA BaseClass; // ClassA only contains virtual functions
#ifdef _USE_CLASS_B
  // Want to change ClassA to ClassB (ClassB : public ClassA)
#elif   _USE_CLASS_C
  // Want to change ClassA to ClassC (ClassC : public ClassA)
#endif
BaseClass.VirtualFunction(); // Call the function (BaseClass now is ClassB or ClassC, Can't be ClassA becuase all functions are virtual)
Hi,

Because you're using the preprocessor, you can just do this:

Code: Select all

#ifdef _USE_CLASS_B
ClassB BaseClass();
#else
ClassC BaseClass();
#endif
BaseClass.VirtualFunction();
Job done. If you want a more general purpose solution without using the preprocessor:

Code: Select all

ClassA *BaseClass = 0;
ClassB b;
ClassC c;
if(use_class_b) {
    BaseClass = &b;
} else {
    BaseClass = &c;
}
Cheers,

James

Re: C++ Class Constructor

Posted: Mon Apr 11, 2011 7:33 am
by Candy
What about:

Code: Select all

class ClassB {};

class ClassC {};

#ifdef SOMETHING
typedef ClassB ClassA;
#else
typedef ClassC ClassA;
#endif

ClassA object;

object.function();
No virtual function necessary in the first place. No overhead, either. It does have the ability to hide breaking bugs until you build the other SOMETHING too.

Re: C++ Class Constructor

Posted: Mon Apr 11, 2011 4:17 pm
by Combuster
I assume it has something to do with minimizing the total amount of code - do really you want to #if every variable declaration instead of changing the type itself?