|
Why do you want to do something like that ? A and B are two completely different classes so, why do you want to be able to pass a B to a function expecting an A object ? It's a bit like asking how can I convert an apple to a car, it doesn't make any sense.
If the objects are related in some way, then I would suggest that they have a common base class and that your function expect a pointer to the base class. Then you can pass a pointer to an instance of A or a pointer to an instance of B but the function will treat them as a pointer to the base class.
But if the class are unrelated, I think you are making a very bad design decision.
|
|
|
|
|
The project is bigger than what I've written down. I know it's usually not safe but we're sure the memory layout of the classes permit this forced cast and that it actually works. My questions still stands. Also, the question is how (if at all) this can be done, not whether it is safe or not.
|
|
|
|
|
Also, the function expects a pointer to an A object, not an A object itself. I'm just looking for a way to tell the compiler I want the (A*) operator implicitly cast so I don't have to change the whole project (which is pretty big).
|
|
|
|
|
Arkh wrote: I know it's usually not safe but we're sure the memory layout of the classes permit this forced cast and that it actually works.
Then state this relation giving them a common base class or interface.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Arkh wrote: but we're sure the memory layout of the classes permit this forced cast and that it actually works
Honnestly, that's a receipt for disaster: if later you have a programmer who wants to document the class and innocently swap two variables of your class, you are doomed. This is an extremly bad practice, and that's one of the reason why type safety is so strong in C++.
Anyway, you still didn't answer the question: WHY do you want something like that ? It doesn't make any sense that your function accept a pointer to A and you pass a pointer to B making believe the function that it is a pointer to A
|
|
|
|
|
Ok here goes. We're migrating our software to run on more platforms. Initially we had something like:
class A : public B {};
void function(B* x) {};
Obviously
A* y;
function(y);
used to work. Now we have some wrapper classes, call them xA (over A) and xB (over B). Therefore:
class xA : protected A {};
class xB : protected B {};
void function(xB* x){};
Since xA is not derived from xB, calling the function as before no longer works.
xA* x;
function(x);
function((xB*)x);
The protected in the inheritence between the base and wrapper classes is necesarry. All functions in A and B are overwritten in xA and xB respectively but no new members are added. This is part of the specs.
Now can you answer the question?
|
|
|
|
|
Why don't you keep your function as it was ? This way you can pass a pointer to xA or a pointer to xB which both inherit from B.
|
|
|
|
|
Because in our software we should no longer have access to classes A and B, only to xA and xB. Classes A and B are specific to the platform we're using now. On other platforms we have classes, say, C and D. But we want to make our software run on all platforms, so functio(B* x) would make no sense in our code if we were running it on the second platform. Any ideas on how to make it work? Anyone?
|
|
|
|
|
I think you still have a bad design decision: your base class should be independant of any platform but these are abstract classes (they can't be instanciated). Then, for each platform, you would create another class which inherits from the base class. Suppose you want to create a class to display a window (both on Windows and Linux). You would do something like this:
class CWindow
{
};
class CWinWindow : public CWindow
{
};
class CLinWindow : public CWindow
{
};
Your function receives a pointer to a CWindow object but should care about the fact that it is for windows or Linux. Then, you should redefine the behavior of your window through virtual functions. Both child classes implements functions like show(..) or move(..) in their own specific way. The rest of your program should in fact only manipulate CWindow pointers.
|
|
|
|
|
both platforms coincidentaly have the same functions in classes and so on, so our design works. only the class names differ. the design works(tested), we just need to get rid of the explicit casts.
more specifically, in our code we use something like:
#ifdef PLATFORM1
class A : protected AfromPlatform1
#else
class A : protected AfromPlatform2
#endif
{
void f();
}
void A::f()
{
#ifdef PLATFORM1
AfromPlatform1::f();
#else
AfromPlatform2::f();
#endif
}
This works, trust me, as I said before, it's tested.
|
|
|
|
|
What are trying to do? What about a good OOP tutorial?
Explicitely casting a pointer of an unrelated object is always a bad idea (well using unitialized pointers, as you did is evene worse).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Can you declare the constructor to take void* instead of void ? All pointer types can be passed as void* , and in C also the other way around.
Of course, I agree with others that what you are doing is a bad idea but hey, we're all grown ups (I hope)
|
|
|
|
|
I'll give it a shot, although it's not exactly a solution since i only want to be able to convert from some pointer types to the type the function is looking for. If the constructor does accept a void* parameter, all pointers would be converted to my class when the function is called and i don't necesarily want that. Also, if you read all the replies from above, you will see that it's no really a bad design or implementation, i was just being greedy about the details, because details would only be useful in explaining the reasons I'm trying to do this but not at all helpful in finding a solution. Any other ideas?
|
|
|
|
|
It didn't work. You can have a constructor that takes a void*, but doesn't help my case. Thanks though for the first constructive reply. Any more ideas?
|
|
|
|
|
Am i to understand this can't be done?
|
|
|
|
|
Cannot you overload the testfunction ?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
It is possible to do this but there would be a lot of functions that would need to be overwritten. It would just be easier to explicitly cast each time a function is called.
|
|
|
|
|
You can't implicitly cast between pointers to objects to unrelated classes. The design of C++ is such that if you want to behave like a complete nutter and do nutty things you can but you have to do something that looks ugly in return.
If you're sure that the two classes are completely type compatible and you won't have any problems later[1] you could use a set of shim functions to hide the disgustingness somewhere else. Bit like a Dorianic portrait, your code looks beautiful but up in the attic...
So if you've got:
void some_function( A *a );
implement an overide:
void some_function( B *b )
{
some_function( reinterpret_cast<A *>( b ) );
}
Ideally what you should have done was implement a set of proxy classes between your platform specific code and the rest of your program, then you'd be just reimplementing a set of interfaces. The sort of hack you're trying to perpetrate might keep management sweet in the short term but in the long term you'll suffer with horrible code. You can't win when you fight a language's type system.
[1] Forgive me for sniggering, but the ammount of times I've heard that from so-called experienced software engineers when they've relied on the binary layout of a class only to have them condemned to using a particular compiler forever more...
|
|
|
|
|
[1] we're not relying on the binary layout of the classes, but on the fact that our classes are just wrappers that look exactly like our platform-specific classes, the only difference being that they have a different name.
As i mentioned before, writing a function override would be even more work than explicitly casting each time a function is called due to the fact that there are a lot of functions.
|
|
|
|
|
So you only use each function once?
I think I get your problem now. You just want to plonk in another class with a similar public interface as another one. There are two ways to get around this sort of problem:
- stick a proxy class in the way and implement this proxy in terms or A or B. You can then use a factory method or other pattern to instantiate the proxy in the right way
- use templates. Templates allow you to use objects with a common interface without regard for what class they are. So you could write:
template <typename T>
void do_something( T *t )
{
t->do_something_cool();
t->gasp_in_amazement_as_i_do_something_cooler();
}
Then you can use the function with any class that supports the two member functions used in the function. Inheritance is not what you need here.
Cheers,
Ash
modified on Thursday, June 17, 2010 4:59 AM
|
|
|
|
|
Hi!
Is there any type casting to convert from Pointer to reference? My function is expecting a pointer but I've a Reference. What to do?
|
|
|
|
|
T.RATHA KRISHNAN wrote: I've a Reference
What do you mean you have a reference ?
Anyway, if you have a variable and need to pass a pointer to a function, you can use the address of operator (& ) to get the address of your variable.
|
|
|
|
|
IrrlichtDevice* device = createDevice(EDT_SOFTWARE, core::dimension2d<u32>(800, 600), 16, false);
I've to pass the above device(pointer) as a reference to the following function:
CEGUI::IrrlichtRenderer& myRenderer = new IrrlichtRenderer(device);
The "IrrlichtRenderer" is a constructor which accepts only a reference not a pointer. I
can not modify the above constructor because it's not mine( a third party library).
Is there any way?
|
|
|
|
|
Well, it is the opposite of what you were saying in you first post. In that case, simply dereference the pointer:
CEGUI::IrrlichtRenderer& myRenderer = new IrrlichtRenderer(*device);
|
|
|
|
|
Hi All,
I am new to this forum. I am struggling with the following bug.
I am working with a CEdit control. programmatically i am changing the value of the RTL reading order menu item value on the CEdit control. Following is the code i am using.
void CGMTextBoxCtrl::SetRightToLeft(BOOL bNewValue)
{
if (bNewValue)
{
m_ulExtendedStyle &= ~WS_EX_LTRREADING;
m_ulExtendedStyle |= WS_EX_RTLREADING;
//long ulExtendedStyle = SetWindowLong(GetSafeHwnd(),GWL_EXSTYLE,WS_EX_RTLREADING);
}
else
{
m_ulExtendedStyle &= ~WS_EX_RTLREADING;
m_ulExtendedStyle |= WS_EX_LTRREADING;
//long ulExtendedStyle = SetWindowLong(GetSafeHwnd(),GWL_EXSTYLE,WS_EX_LTRREADING);
}
SetModifiedFlag();
RecreateControlWindow();
}
After executing this, the Right to left reading order option is getting checked when i set the value to true. But the text in the control remains LTR.
I tried with Send message. But that couldn't help me. Can anyone please let me know how to achieve this ASAP. its very urgent.
Thanks in advance,
Lucky
|
|
|
|