C++ Class Constructor

Programming, for all ages and all languages.
Post Reply
Wolftein
Posts: 14
Joined: Wed Oct 15, 2008 3:39 pm

C++ Class Constructor

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

User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: C++ Class Constructor

Post 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);
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Wolftein
Posts: 14
Joined: Wed Oct 15, 2008 3:39 pm

Re: C++ Class Constructor

Post 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();
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: C++ Class Constructor

Post 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.
Wolftein
Posts: 14
Joined: Wed Oct 15, 2008 3:39 pm

Re: C++ Class Constructor

Post 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)
User avatar
gravaera
Member
Member
Posts: 737
Joined: Tue Jun 02, 2009 4:35 pm
Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.

Re: C++ Class Constructor

Post 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
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: C++ Class Constructor

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
linuxfood
Member
Member
Posts: 38
Joined: Wed Dec 31, 2008 12:22 am

Re: C++ Class Constructor

Post 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.
User avatar
linuxfood
Member
Member
Posts: 38
Joined: Wed Dec 31, 2008 12:22 am

Re: C++ Class Constructor

Post 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.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Re: C++ Class Constructor

Post 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
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re: C++ Class Constructor

Post 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.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: C++ Class Constructor

Post 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?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply