Immortal Nephi wrote:
I thought that you might find an interesting code. Perhaps, you have
seen this before. I created two classes of A and B. Two classes have
different objects. The class Obj has a relationship to class A and
class B which is called composition.
The class Obj has one variable which is a pointer to member function
in array. You can't bind member function of both class A and class B
because they do not belong to class Obj. I use reinterpret_cast to
convert from class A to class Obj before pointer to member function is
invoked.
I believe that my code is the alternative replacement so I don't use
inheritance and polymorphism. It is easier to extract class. What do
you think?
Your code has undefined behaviour, not to mention that the
compiler that is supposed to compile your
'reinterpret_cast' will exhibit undefined behaviour (most
likely). Aside from that, you're good...
How did you say undefined behavior? I played with
debugging. I found out that reinterpret_cast array did
assign memory address correctly, but *this* pointer in class
A and class B assigns to the wrong memory address.
For example:
class ....
{
int a;
int b;
int c;
}
*this* pointer should always assigns to data member as a,
but it did assigns to either data member as b or c. The
data was misplaced from a to b like memory misalignment.
I guess there is no alternative replacement to undefined
reinterpret_cast array, but switch block is the answer to each class'
member function.
Do you know if there is another way? What about template array?
You can use union:
class Obj
{
public:
void Run()
{
this->*(pO[0].runA)();
this->*(pO[1].runB)();
That shouldn't compile, given the union you defined below; this
isn't the right type. (It's also lacking some parentheses.)
}
private:
A a;
B b;
union To
{
void A::*runA();
void B::*runB();
};
static To const pO[2];
};
// not sure about initialisation - perhaps only possible in C99
Obj::To const Obj:
O[2] =
{
{&A::Run},
{&B::Run}
};
You could use assignment somewhere, e.g. in an if in the
constructor. But once you've gotten the correct types in the
array, you have to call the function with the correct type; the
whole point of his exercise was to lie to the compiler, in order
to ensure that it generated incorrect code (and probably to use
some exotic and generally slow technique, like pointers to
members, rather than the usual faster technique of virtual
functions).
James Kanze,
Hi, James. He is correct to point that Michael's post about union is
not working and C++ Compiler does not compile.
My question is always unanswered when I did research to find out
pointer to member function array.
Why member function pointer is **rarely** used in any C++ class? The
optimization speed shows the result here below.
C style code--
Example 1:
switch (...)
{
case 0x00:
func00();
case 0x01:
func01();
....
....
case 0xFF:
funcFF();
};
All global functions in the switch block is fair speed.
Example 2:
void func00();
void func01(),
....
....
void funcFF();
void (*pfn)() = { func00, func01, ..., ..., funcFF };
All global functions are stored in pointer to global function array is
faster than example 1 above because the code reads indirection once
before accesses memory address directly.
C++ style code--
Example 3:
class foo
{
void func00() {}
void func01() {}
....
....
void funcFF() {}
void ( *foo::*pfn[ 0x100 ] )();
};
Example 4:
class foo
{
void func00() {}
void func01() {}
....
....
void funcFF() {}
static void ( *foo::*pfn[ 0x100 ] )();
};
You can see non-static pointer to member function array in example 3
and static pointer to member function array in example 4.
Example 4 is faster than example 3 because example 4 is identical to
example 2 and static is declared.
Example 5:
class subFoo00 {};
class subFoo01 {};
....
....
class subFooFF {};
class foo
{
subFoo1 sf00;
subFoo2 sf01;
....
....
subFooFF sfFF;
void run()
{
switch (...)
{
case 0x00:
sf00.func00();
....
case 0x01:
sf01.func01();
....
....
case 0xFF:
sfFF.funcFF();
};
};
};
Do you see my point in example 5? class foo has a relationship to all
256 classes of subFoo00, subFoo01, ..., subFooFF. I extract from one
big class into 256 subclasses. All 256 subclasses are the alternative
replacement to inheritance and polymorphism.
Compare example 1 and example 5. I am unable to tell the speed
measurement because both example 1 and example 5 are very close.
Back to James Kanze' note --
You could use assignment somewhere, e.g. in an if in the
constructor. But once you've gotten the correct types in the
array, you have to call the function with the correct type; >the whole point of his exercise was to lie to the compiler,
in >order to ensure that it generated incorrect code (and
probably to use some exotic and generally slow technique,
like pointers to members, rather than the usual faster
technique of virtual functions).
How do you say *the usual faster technique of virtual function*?
class foo is the base class. All 256 classes are derived from base
class foo. They do not have composition. They enable to use
inheritance and polyporphism.
The virtual function has indirection overhead because it uses
indirection twice every time virtual function is invoked.
I need to decide whatever I want to choose either example 4 or example
5 or I have to use inheritance and polymorphism.
In the end of my writing. Why pointer to member function is rarely
used?
Thanks for being patience. Smile...