Dim St Thomas wrote:
I am replying to my own message as the reply below has not yet
appeared on Google, so I copied from my free newsfeed.
Kai-Uwe Bux wrote: Dim St Thomas wrote:
Say you have a library with a header file that defines two classes:
class A
{
protected:
virtual void draw();
};
class B
{
public:
A *getWidget() { return m_a; }
private:
A *m_a;
};
Is there any way of creating an instance of class B such that when itcalls the virtual draw function of m_a it will call a user derived
version of draw? The two ways I can think of are making the m_a
variable public and setting it equal to a class derived from A or
somehow modifying the virtual function table of the pointer returned
by getWidget(). I assume these are both hacks that are dependent on
the behaviour of the compiler. Has anyone got this to work using
Visual C++?
Thanks
If you had code like
B b;
...
b.getWidget()->draw();
the last line will effectively translate to b.m_a->draw(). Since draw()
is virtual, it will invoke whichever method is the right one for the
object that b.m_a points to. This object can be of any type derived from
A.
However your class definitions above seem not to allow for assigning
*any* value to b.m_a. How do you intend to initialize this pointer
anyway? You certainly want this pointer to point somewhere meaningfull?
Once it does, I do not really see a problem with the statement:
b.getWidget()->draw();
What is it that I am missing?
The header files are from a library that I don't have access to the
source code. The B class creates an instance of A internally (probably
during the constructor). Ideally there would be a setWidget function,
but as there isn't I have to find some way of hacking it to do what I
want.
Sounds like you want to hack a setWidget() method from the outside. One
idea would be to do something like
void setWidget( B& b, A* a ) {
char * b_data = (char*) &b;
// and now do some manipulations to b_data[...] to
// set the field b.m_a
}
For instance, on my machine the following program
#include <iostream>
class B{
private:
unsigned int l;
public:
unsigned int get( void ) {
return( l );
}
}; // B
void set ( B& b, unsigned int k ) {
char* b_data = (char*) &b;
char* k_data = (char*) &k;
for ( int i = 0; i < 4; ++i ) {
b_data[i] = k_data[i];
}
}
int main ( void ) {
B b;
std::cout << b.get() << std::endl;
set( b, 6 );
std::cout << b.get() << std::endl;
}
prints
3221224484
6
I would think, however, that the setWidget() method was left out for a
reason and that you are very likely to break all sorts of stuff inside the
object b.
Hope this helps
Kai-Uwe Bux