Thread: Class function pointers

  1. #31
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Yes that works and I've used it before but the typical misuse would be this:


    B MyB;

    A MyA=B.GetA();
    If you make the A* a protected member of a member functor in B, I don't think you should ever run into something like that. I suppose this involves 2 function calls anyway, but I'm not entirely sure what your goal is in eliminating the first call (admittedly, I didn't read through the first page of the thread) - if you just want something that can be used like a function pointer (i.e. changed to point to different member functions in A), then this should work fine. On the other hand, if you're trying to optimize here then I suppose it isn't the greatest solution.

    **EDIT**
    I see now that this isn't what you want (the point of this is for optimization, right?). You can inline the operator() of the functor, but then it's equivalent (and worse) to creating intermediate inline functions as members of B.

    If you're going the inlining route and you're using MSVC, then I believe there's a __forceline directive (or something to that effect) that you can use to ensure inlining wherever possible - to take some of the 'guesswork' out of whether inlining will occur or not.
    Last edited by Hunter2; 02-15-2005 at 11:52 AM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  2. #32
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    2)Assign the address of the function in A to the function pointer
    You can't.

    Each function has a prolog and epilog like __thiscall and __stdcall, __cdecl, __fastcall etc. If you declare the function inside of the class no matter if it is a function pointer or not, it seems that is uses __thiscall. You cannot cast this away because it is saying you need an object of some type to call this function with.

    The functions in A are not private, the instance of A in B is protected, therefore it doesn't matter if A's functions are public or not...you cannot get to the instance of A in B from outside of B. I do not want to return the instance of A in B - essentially I need to limit certain functions. But there is a better way and the inline method is where I'm headed as well. Also will make vital functions protected so that even if you have a copy of A, you still cannot call those functions unless you are in A or a derivation of A.

    The prolog/epilog for __stdcall would be something like this (I think)

    Code:
    @MyFunc:
      push  ebp
      mov   esp,ebp
    
      ...
    
      pop ebp
    Read the compiler docs as each one is explained including who is responsible for cleaning up the stack.
    The reason I could do this in assembly is because most of C++ is compiler-side rules, that is they are only in effect inside of the compiler. Once the object code has been written, I can still gain access to anything I want from pure asm code. However, this is not a good practice and I won't get into manually editing my C++ code.

    The __pascal modifier means that parameters are pushed from right to left and the __cdecl means they are pushed from right to left (or vice versa I forget).

    So if you have a function like so in 32-bit code:

    unsigned int Subtract(unsigned int v1,unsigned int v2)

    To call this:

    Code:
      push [v2]
      push [v1]
      call Subtract
    
      Subtract:
        push  ebp
        mov ebp,esp
    
        mov  eax,[ebp+12]
        sub   eax,[ebp+8]
        
        pop   ebp
    Which is far different from:
    Code:
      push [v1]
      push [v2]
      call Subtract
    
      Subtract:
        push  ebp
        mov ebp,esp
    
        mov  eax,[ebp+12]
        sub   eax,[ebp+8]
        
        pop   ebp
    The two will yield very different results. And this is of course barring the fact that name mangling will occur with C++, unless you explicity tell it not to mangle them.
    Last edited by VirtualAce; 02-15-2005 at 10:25 PM.

  3. #33
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Sorry, I don't understand much of that. Here is my latest attempt--I have no idea if it is optimized the way you want--but it keeps users from being able to get at AInstance inside the Object class:

    Code:
    #include<iostream>
    using namespace std;
    
    class A
    {
      public:
        void Func(int x) {cout<<x<<endl;}
    };
    
    class Object
    {
        A AInstance;
        void (A::*pFunc)(int);
       
    public:
         
        Object(void)
        {
            pFunc = &A::Func;
        }
        
        void operator()(int x)
        {
            (AInstance.*pFunc)(x);
        }
    };
    
    
    
    
    int main()
    {
        Object o;
        o(3);
        
        return 0;
    }
    Last edited by 7stud; 02-15-2005 at 12:18 PM.

  4. #34
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    This method goes the inlined-intermediate route as well, except that it adds an extra indirection by calling A's member function through a function pointer.. it's unsuitable for the same reason as my functor idea
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #35
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I didn't know this would be that difficult. But then most people don't use function pointers in a class to point to functions in another separate class.

    Perhaps I will do the thing I really don't want to do: derive the entire base class for the engine from multiple bases and ensure that only one copy is ever in the base by using virtual.

    Code:
    class CD3DApp:virtual public CDXInput, virtual public CDXSoundEmitter
    {
    }
    But that is so hideous.

  6. #36
    Registered User
    Join Date
    Dec 2004
    Posts
    95
    Allow access to the object(s) in question with get functions, or at least a safe wrapper object that only lets users call some functions on the inner object, and/or does the necessary addref/release.

    Adding forwarding functions, etc to the main app class would not be a great design choice IMO.

    From the info. you've presented, it seems what's needed is a bit of a design change, rather than arcane methods.

  7. #37
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    OK, I'm just here to clear up some confusion about calling conventions.
    The keywords MSVC supports are __cdecl, __stdcall and __fastcall.
    In addition, error messages may contain the __thiscall "keyword", but its use is not valid in code.

    So what are they about?
    The first three dictate how parameter handling happens on the function call.
    The fourth, thiscall, merely indicates that the function is a member function and should receive the additional this pointer as parameter. This convention is not mutually exclusive with the others; in fact, every COM method is a __thiscall __stdcall.

    __cdecl:
    The standard C convention dictates that parameters are pushed on the stack from right to left. The caller is responsible for cleaning up the stack; this means that the caller can push as many arguments as he wants. Only this convention allows variable argument lists.
    The standard C name mangling prefixes the function name with an underscore.

    __stdcall:
    The Pascal convention dictates that parameters are pushed on the stack from left to right. The callee is responsible for cleaning up the stack by means of the parametrized ret instruction; as such, passing variable argument lists is not possible, given that the callee has no way of knowing how much was really passed.
    The standard C name mangling under this convention prefixes the function name with an underscore, and in addition appends an @-sign followed by the number of bytes that the function expects in its parameter list.

    __fastcall:
    This is essentially the same as __stdcall, but with some rules as to how some parameters are passed in registers instead.


    __thiscall merely adds an additional hidden parameter. I believe it always adds it as the left-most one, meaning that it would be at ebp+4 under __cdecl, but ebp+(bytes in declared parameter list)+4 under __stdcall.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #38
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    In addition, error messages may contain the __thiscall "keyword", but its use is not valid in code.
    Yet.

    Seems that future plans may incorporate this into the next generation of compilers. The error message I get is that __fastcall is a reserved future symbol.

    But CornedBee hit the nail on the head. I don't do much assembly anymore so my knowledge of declarations in C and what they do were a bit rusty and for that I do apologize...but I did warn ya.

    Most 32-bit programs start parameter lists at ebp+8. At ebp+0 is the previous value of ebp, ebp+4 is the return address of the caller, ebp+8 is the first function parameter. But this can be changed by using the above declarations and the order in which parameters are pushed can also be changed.

    But what CornedBee said about __thiscall is exactly why my function pointers are not working. And since the language was not intended to directly support what I'm doing....then I'm doing it wrong.

    I will change my structure and setup to work with the language instead of against it.
    Last edited by VirtualAce; 02-16-2005 at 01:39 PM.

  9. #39
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Seems that future plans may incorporate this into the next generation of compilers.
    I don't see what the use would be. A global/static function is a global/static function and a member function is a member function. Member functions are __thiscall and global/static functions are not. End of story, for me.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  10. #40
    Registered User
    Join Date
    Feb 2005
    Posts
    19
    You should really try to avoid function pointers when you're working with objects and just pass a pointer of the object containing the function itself. I used function pointers before and I found them to be a real pain. It is a lot better to use references to objects instead. You'll probably have to break some encapsulation though but that's C++. When it comes to global functions I might use a function pointer.

  11. #41
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    don't see what the use would be.
    Yeah I don't either but that's the assumption I made based on the strange error message I received from the compiler. Here let me duplicate the error.

    nonstandard extension used : '__thiscall' keyword reserved for future use
    What use might this be?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  4. Problem with function pointers
    By vNvNation in forum C++ Programming
    Replies: 4
    Last Post: 06-13-2004, 06:49 AM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM