C++ rookie having trouble. Anybody care to try to help?

Discussion in 'C++' started by Don Bruder, Sep 18, 2003.

  1. Don Bruder

    Don Bruder Guest

    Got a stumper here. I imagine that for someone experienced in C++, this
    is too pathetic for words. For a rookie, using this project as a sort
    of "midterm exam" in his self-taught "how to program in C++" course,
    it's seeming to be an insurmountable problem. Can anyone assist? I'm at
    wit's end here. Everything *LOOKS* (to this rookie, anyway) correct,
    but the compiler is barfing on it.

    Here's the class declaration for Bar
    class Bar
    {
    private:
    int Done;
    char File[254];
    float PartDone;
    int Time;
    char SaveTo[254];
    int DRate;
    int URate;
    int Action;

    public:
    Bar();
    ~Bar();
    void Finished(void);
    void Failed(void);
    void Error(char *ErrorMsg);
    void Display(float PercentDone, int Time, int DRate,
    int URate, int Action);
    void ChooseFile(char *DefaultName, int MaxFileNameSize,
    char *SaveTo, char *Dir);
    void NewPath(char *Path);
    void DoIt(char **argv);
    };

    Here's the header file that declares routine Foo:

    int Foo(char **args,
    void (*FileFunc)(char *, int, char *, char *),
    void (*StatusFunc)(float, int, int, int, int),
    void (*FinishFunc)(void),
    void (*ErrorFunc)(char *),
    int *DoneFlag,
    int Cols,
    void (*PathFunc)(char *)
    );

    And finally, here's where/how Foo gets called:

    void Bar::DoIt(char **argv)

    {
    Foo(argv,
    (void (*)(char *, int, char *, char *)) this->ChooseFile, <--- 1
    (void (*)(float, int, int, int, int)) this->Display, <--- 2
    (void (*)(void)) this->Finished, <--- 3
    (void (*)(char *)) this->Error, <--- 4
    &this->Done,
    80,
    (void (*)(char *)) this->NewPath <--- 5
    );
    if (!this->Done)
    this->Failed();
    }

    int main(int argc, char **argv)

    {
    // I just plain don't care about argc, so shut up about it, compiler!
    #pragma unused (argc)

    Bar FooBar;

    FooBar.DoIt(argv);
    }

    Lines marked on the right margin with "<--- #" indicate where the
    compiler barfs at me. The specific errors reported for each "#" are:

    1:
    Error : illegal explicit conversion from 'void' to 'void (*)(char *,
    int, char *, char *)'
    Baz.c++ line 268 (void (*)(char *, int, char *, char *))
    this->ChooseFile,

    2:
    Error : illegal explicit conversion from 'void' to 'void (*)(float,
    int, int, int, int)'
    Baz.c++ line 269 (void (*)(float, int, int, int, int)) this->Display,

    3:
    Error : illegal explicit conversion from 'void' to 'void (*)()'
    BTDownloadHeadless.c++ line 270 (void (*)(void)) this->Finished,

    4:
    Error : illegal explicit conversion from 'void' to 'void (*)(char *)'
    Baz.c++ line 271 (void (*)(char *)) this->Error,

    5:
    Error : illegal explicit conversion from 'void' to 'void (*)(char *)'
    Baz.c++ line 274 (void (*)(char *)) this->NewPath

    As can be seen, they're basicaly the same error in all cases, with
    variations for the exact cast that's happening.

    So what, precisely, am I doing wrong??? Everything I can find in either
    K&R C, 2nd, or Stroustrup C++ 3rd shows me that this *SHOULD BE*
    perfectly legal code (although I freely grant that it may be *CRAPPY*
    code, style-wise... That's a whole different topic...) yet for some
    reason, I'm getting compiler barfs that are stopping me in my tracks.
    The 5 errors listed are the only ones anywhere in the code (at least as
    far as the compiler reports to this point) - everything else except the
    file containing main() and DoIt() compiles without complaint.

    Anybody got some advice for me? What is it I'm doing wrong, and how/why
    is it wrong?

    --
    Don Bruder - <--- Preferred Email - SpamAssassinated.
    Hate SPAM? See <http://www.spamassassin.org> for some seriously great info.
    I will choose a path that's clear: I will choose Free Will! - N. Peart
    Fly trap info pages: <http://www.sonic.net/~dakidd/Horses/FlyTrap/index.html>
    Don Bruder, Sep 18, 2003
    #1
    1. Advertising

  2. Don Bruder

    White Wolf Guest

    Don Bruder wrote:
    [SNIP]
    > (void (*)(char *, int, char *, char *)) this->ChooseFile,


    As far as I understand you need to take the address of that function. But
    you cannot. It is a call to a member function. It has no address
    convertable to a "normal" C-style function pointer due to the

    > So what, precisely, am I doing wrong??? Everything I can find in
    > either K&R C,


    K&R C has no classes and member functions, so I doubt that it contains
    anything like the above.

    > 2nd, or Stroustrup C++ 3rd shows me that this *SHOULD
    > BE* perfectly legal code


    I also very much doubt that Stroustrup would say that you can convert a
    member function (pointer) into a normal C-style function pointer.

    Please, if you really wish to learn about this function pointer things read
    this excellent article from Herb Sutter:

    http://www.cuj.com/documents/s=8464/cujcexp0308sutter/

    It is describing a candidate for a new standard library element, one which
    can be used to pass around any functions, be it member or not. The existing
    implementation of it you can find at

    http://www.boost.org

    --
    WW aka Attila
    White Wolf, Sep 18, 2003
    #2
    1. Advertising

  3. Don Bruder

    Mike Wahler Guest

    "Don Bruder" <> wrote in message
    news:0Ypab.22630$...
    > Got a stumper here. I imagine that for someone experienced in C++, this
    > is too pathetic for words. For a rookie, using this project as a sort
    > of "midterm exam" in his self-taught "how to program in C++" course,
    > it's seeming to be an insurmountable problem. Can anyone assist? I'm at
    > wit's end here. Everything *LOOKS* (to this rookie, anyway) correct,
    > but the compiler is barfing on it.
    >
    > Here's the class declaration for Bar
    > class Bar
    > {
    > private:
    > int Done;
    > char File[254];
    > float PartDone;
    > int Time;
    > char SaveTo[254];
    > int DRate;
    > int URate;
    > int Action;
    >
    > public:
    > Bar();
    > ~Bar();
    > void Finished(void);
    > void Failed(void);
    > void Error(char *ErrorMsg);
    > void Display(float PercentDone, int Time, int DRate,
    > int URate, int Action);
    > void ChooseFile(char *DefaultName, int MaxFileNameSize,
    > char *SaveTo, char *Dir);
    > void NewPath(char *Path);
    > void DoIt(char **argv);
    > };
    >
    > Here's the header file that declares routine Foo:
    >
    > int Foo(char **args,
    > void (*FileFunc)(char *, int, char *, char *),
    > void (*StatusFunc)(float, int, int, int, int),
    > void (*FinishFunc)(void),
    > void (*ErrorFunc)(char *),
    > int *DoneFlag,
    > int Cols,
    > void (*PathFunc)(char *)
    > );
    >
    > And finally, here's where/how Foo gets called:
    >
    > void Bar::DoIt(char **argv)
    >
    > {
    > Foo(argv,
    > (void (*)(char *, int, char *, char *)) this->ChooseFile, <--- 1
    > (void (*)(float, int, int, int, int)) this->Display, <--- 2
    > (void (*)(void)) this->Finished, <--- 3
    > (void (*)(char *)) this->Error, <--- 4
    > &this->Done,
    > 80,
    > (void (*)(char *)) this->NewPath <--- 5
    > );
    > if (!this->Done)
    > this->Failed();
    > }
    >
    > int main(int argc, char **argv)
    >
    > {
    > // I just plain don't care about argc, so shut up about it, compiler!
    > #pragma unused (argc)
    >
    > Bar FooBar;
    >
    > FooBar.DoIt(argv);
    > }
    >
    > Lines marked on the right margin with "<--- #" indicate where the
    > compiler barfs at me. The specific errors reported for each "#" are:
    >
    > 1:
    > Error : illegal explicit conversion from 'void' to 'void (*)(char *,
    > int, char *, char *)'
    > Baz.c++ line 268 (void (*)(char *, int, char *, char *))
    > this->ChooseFile,
    >
    > 2:
    > Error : illegal explicit conversion from 'void' to 'void (*)(float,
    > int, int, int, int)'
    > Baz.c++ line 269 (void (*)(float, int, int, int, int)) this->Display,
    >
    > 3:
    > Error : illegal explicit conversion from 'void' to 'void (*)()'
    > BTDownloadHeadless.c++ line 270 (void (*)(void)) this->Finished,
    >
    > 4:
    > Error : illegal explicit conversion from 'void' to 'void (*)(char *)'
    > Baz.c++ line 271 (void (*)(char *)) this->Error,
    >
    > 5:
    > Error : illegal explicit conversion from 'void' to 'void (*)(char *)'
    > Baz.c++ line 274 (void (*)(char *)) this->NewPath
    >
    > As can be seen, they're basicaly the same error in all cases, with
    > variations for the exact cast that's happening.
    >
    > So what, precisely, am I doing wrong??? Everything I can find in either
    > K&R C, 2nd, or Stroustrup C++ 3rd shows me that this *SHOULD BE*
    > perfectly legal code (although I freely grant that it may be *CRAPPY*
    > code, style-wise... That's a whole different topic...) yet for some
    > reason, I'm getting compiler barfs that are stopping me in my tracks.
    > The 5 errors listed are the only ones anywhere in the code (at least as
    > far as the compiler reports to this point) - everything else except the
    > file containing main() and DoIt() compiles without complaint.
    >
    > Anybody got some advice for me? What is it I'm doing wrong, and how/why
    > is it wrong?


    The lines giving the errors look quite suspicious to me.
    AFAIK, a pointer to a member function and a pointer to
    a nonmember function are not 'compatible', and there's
    no defined way to convert from one to the other.

    What on Earth are you trying to do?

    Have you tried using overloaded or virtual functions
    to do the 'dispatching' it looks like you're trying to do?

    -Mike
    Mike Wahler, Sep 18, 2003
    #3
  4. Don Bruder

    Alexei Betin Guest

    Your problem is that member functions have an implicit argument
    - the "this" pointer, and therefore their "true" signature - and type
    depends on the class they are in.

    In other words, functions

    int f1( int a );
    int A::f2( int a );
    int B::f3( int a );

    have, in fact quite different signatures and cannot be used interchangeably,
    namely only the 1st one has a type of int (*) (int), while the second one
    has a type of int (A::*) (int) etc.

    Hope, this helps
    ~Alexei

    "Don Bruder" <> wrote in message
    news:0Ypab.22630$...
    > Got a stumper here. I imagine that for someone experienced in C++, this
    > is too pathetic for words. For a rookie, using this project as a sort
    > of "midterm exam" in his self-taught "how to program in C++" course,
    > it's seeming to be an insurmountable problem. Can anyone assist? I'm at
    > wit's end here. Everything *LOOKS* (to this rookie, anyway) correct,
    > but the compiler is barfing on it.
    >
    > Here's the class declaration for Bar
    > class Bar
    > {
    > private:
    > int Done;
    > char File[254];
    > float PartDone;
    > int Time;
    > char SaveTo[254];
    > int DRate;
    > int URate;
    > int Action;
    >
    > public:
    > Bar();
    > ~Bar();
    > void Finished(void);
    > void Failed(void);
    > void Error(char *ErrorMsg);
    > void Display(float PercentDone, int Time, int DRate,
    > int URate, int Action);
    > void ChooseFile(char *DefaultName, int MaxFileNameSize,
    > char *SaveTo, char *Dir);
    > void NewPath(char *Path);
    > void DoIt(char **argv);
    > };
    >
    > Here's the header file that declares routine Foo:
    >
    > int Foo(char **args,
    > void (*FileFunc)(char *, int, char *, char *),
    > void (*StatusFunc)(float, int, int, int, int),
    > void (*FinishFunc)(void),
    > void (*ErrorFunc)(char *),
    > int *DoneFlag,
    > int Cols,
    > void (*PathFunc)(char *)
    > );
    >
    > And finally, here's where/how Foo gets called:
    >
    > void Bar::DoIt(char **argv)
    >
    > {
    > Foo(argv,
    > (void (*)(char *, int, char *, char *)) this->ChooseFile, <--- 1
    > (void (*)(float, int, int, int, int)) this->Display, <--- 2
    > (void (*)(void)) this->Finished, <--- 3
    > (void (*)(char *)) this->Error, <--- 4
    > &this->Done,
    > 80,
    > (void (*)(char *)) this->NewPath <--- 5
    > );
    > if (!this->Done)
    > this->Failed();
    > }
    >
    > int main(int argc, char **argv)
    >
    > {
    > // I just plain don't care about argc, so shut up about it, compiler!
    > #pragma unused (argc)
    >
    > Bar FooBar;
    >
    > FooBar.DoIt(argv);
    > }
    >
    > Lines marked on the right margin with "<--- #" indicate where the
    > compiler barfs at me. The specific errors reported for each "#" are:
    >
    > 1:
    > Error : illegal explicit conversion from 'void' to 'void (*)(char *,
    > int, char *, char *)'
    > Baz.c++ line 268 (void (*)(char *, int, char *, char *))
    > this->ChooseFile,
    >
    > 2:
    > Error : illegal explicit conversion from 'void' to 'void (*)(float,
    > int, int, int, int)'
    > Baz.c++ line 269 (void (*)(float, int, int, int, int)) this->Display,
    >
    > 3:
    > Error : illegal explicit conversion from 'void' to 'void (*)()'
    > BTDownloadHeadless.c++ line 270 (void (*)(void)) this->Finished,
    >
    > 4:
    > Error : illegal explicit conversion from 'void' to 'void (*)(char *)'
    > Baz.c++ line 271 (void (*)(char *)) this->Error,
    >
    > 5:
    > Error : illegal explicit conversion from 'void' to 'void (*)(char *)'
    > Baz.c++ line 274 (void (*)(char *)) this->NewPath
    >
    > As can be seen, they're basicaly the same error in all cases, with
    > variations for the exact cast that's happening.
    >
    > So what, precisely, am I doing wrong??? Everything I can find in either
    > K&R C, 2nd, or Stroustrup C++ 3rd shows me that this *SHOULD BE*
    > perfectly legal code (although I freely grant that it may be *CRAPPY*
    > code, style-wise... That's a whole different topic...) yet for some
    > reason, I'm getting compiler barfs that are stopping me in my tracks.
    > The 5 errors listed are the only ones anywhere in the code (at least as
    > far as the compiler reports to this point) - everything else except the
    > file containing main() and DoIt() compiles without complaint.
    >
    > Anybody got some advice for me? What is it I'm doing wrong, and how/why
    > is it wrong?
    >
    > --
    > Don Bruder - <--- Preferred Email - SpamAssassinated.
    > Hate SPAM? See <http://www.spamassassin.org> for some seriously great

    info.
    > I will choose a path that's clear: I will choose Free Will! - N. Peart
    > Fly trap info pages:

    <http://www.sonic.net/~dakidd/Horses/FlyTrap/index.html>
    Alexei Betin, Sep 18, 2003
    #4
  5. Alexei Betin wrote:

    > Your problem is that...

    <snip>

    Please don't top. Read section 5 of the FAQ for posting guidelines. In
    particular, read this:

    http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.4

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Sep 18, 2003
    #5
  6. Don Bruder

    Alexei Betin Guest

    "Kevin Goodsell" <> wrote in message
    news:huqab.8647$...
    > Alexei Betin wrote:
    >
    > > Your problem is that...

    > <snip>
    >
    > Please don't top. Read section 5 of the FAQ for posting guidelines. In
    > particular, read this:
    >


    got you, sorry, haven't been here a while...

    > http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.4
    >
    > -Kevin
    > --
    > My email address is valid, but changes periodically.
    > To contact me please use the address from a recent posting.
    >
    Alexei Betin, Sep 18, 2003
    #6
  7. Alexei Betin <> spoke thus:

    > Your problem is that member functions have an implicit argument
    > - the "this" pointer, and therefore their "true" signature - and type
    > depends on the class they are in.


    > In other words, functions


    > int f1( int a );
    > int A::f2( int a );
    > int B::f3( int a );


    > have, in fact quite different signatures and cannot be used interchangeably,
    > namely only the 1st one has a type of int (*) (int), while the second one
    > has a type of int (A::*) (int) etc.


    Can this be mitigated somewhat by adding _closure to the prototypes...?

    --
    Christopher Benson-Manica | Jumonji giri, for honour.
    ataru(at)cyberspace.org |
    Christopher Benson-Manica, Sep 19, 2003
    #7
  8. Christopher Benson-Manica wrote:
    >
    > Can this be mitigated somewhat by adding _closure to the prototypes...?


    "_closure"? What is that (other than a name reserved for the
    implementation's use in the global namespace)?

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Sep 19, 2003
    #8
  9. Don Bruder

    Mike Wahler Guest

    "Christopher Benson-Manica" <> wrote in message
    news:bkfo08$mgl$...
    > Alexei Betin <> spoke thus:
    >
    > > Your problem is that member functions have an implicit argument
    > > - the "this" pointer, and therefore their "true" signature - and type
    > > depends on the class they are in.

    >
    > > In other words, functions

    >
    > > int f1( int a );
    > > int A::f2( int a );
    > > int B::f3( int a );

    >
    > > have, in fact quite different signatures and cannot be used

    interchangeably,
    > > namely only the 1st one has a type of int (*) (int), while the second

    one
    > > has a type of int (A::*) (int) etc.

    >
    > Can this be mitigated somewhat by adding _closure to the prototypes...?


    There's no such keyword in C++. Is that some language
    extension provided by your implementation?

    See http://www.parashift.com/c -faq-lite/pointers-to-members.html

    -Mike
    Mike Wahler, Sep 19, 2003
    #9
  10. Don Bruder

    Alexei Betin Guest

    "Christopher Benson-Manica" <> wrote in message
    news:bkfo08$mgl$...
    > Alexei Betin <> spoke thus:
    >

    <SNIP>
    > > In other words, functions

    >
    > > int f1( int a );
    > > int A::f2( int a );
    > > int B::f3( int a );

    >
    > > have, in fact quite different signatures and cannot be used

    interchangeably,
    > > namely only the 1st one has a type of int (*) (int), while the second

    one
    > > has a type of int (A::*) (int) etc.

    >
    > Can this be mitigated somewhat by adding _closure to the prototypes...?
    >


    Not sure what _closure is.
    If in fact you don't need the object instance - then use a static function
    and you'll be fine, namely

    static int A::f4( int )
    has the same type as
    int f1( int a );
    and either can be passed to a function expecting int (*) (int)

    But if it does need the object as a hidden argument to work on then how
    can you possibly "mitigate" that?

    You can do a forceful cast but the consequences will be disasterous
    when it tries to access memory where it thinks "this" argument should be
    found
    (and maybe even before that due to a different memory layout for arguments
    passing) - that is why the compiler will not allow that without
    reinterpret_cast
    or C-style cast.

    ~Alexei

    > --
    > Christopher Benson-Manica | Jumonji giri, for honour.
    > ataru(at)cyberspace.org |
    Alexei Betin, Sep 19, 2003
    #10
  11. Mike Wahler <> spoke thus:

    > There's no such keyword in C++. Is that some language
    > extension provided by your implementation?


    Apparently yes. Sorry to bring it up. (one of I'm sure many reasons for
    newbs like me to dislike starting with a complex environment like Borland C++
    Builder, with lots of code written by other people to boot - can't tell what's
    "standard" and what's implementation-defined...)

    --
    Christopher Benson-Manica | Jumonji giri, for honour.
    ataru(at)cyberspace.org |
    Christopher Benson-Manica, Sep 20, 2003
    #11
  12. Christopher Benson-Manica wrote:

    > Mike Wahler <> spoke thus:
    >
    >
    >>There's no such keyword in C++. Is that some language
    >>extension provided by your implementation?

    >
    >
    > Apparently yes. Sorry to bring it up. (one of I'm sure many reasons for
    > newbs like me to dislike starting with a complex environment like Borland C++
    > Builder, with lots of code written by other people to boot - can't tell what's
    > "standard" and what's implementation-defined...)


    Technically "implementation-defined" has a specific meaning that doesn't
    apply here. Just thought I'd clarify to avoid future confusion. When the
    standard describes something as "implementation-defined" it means that
    an implementation is required to prescribe a particular behavior and
    document that behavior. It may differ from one implementation to the
    next, but must be consistent and as documented.

    What you are referring to is a language extension.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Sep 21, 2003
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Darrel
    Replies:
    3
    Views:
    448
  2. Martin v. =?iso-8859-15?q?L=F6wis?=

    Re: Tkiniter proposed enhancement; anybody care?

    Martin v. =?iso-8859-15?q?L=F6wis?=, Jun 27, 2003, in forum: Python
    Replies:
    0
    Views:
    642
    Martin v. =?iso-8859-15?q?L=F6wis?=
    Jun 27, 2003
  3. =?ISO-8859-1?Q?Gerhard_H=E4ring?=

    Anybody else having problem *sending* mail to this list?

    =?ISO-8859-1?Q?Gerhard_H=E4ring?=, Sep 3, 2003, in forum: Python
    Replies:
    3
    Views:
    306
    Terry Reedy
    Sep 6, 2003
  4. mr_burns
    Replies:
    1
    Views:
    72
    @(none)
    Jan 9, 2005
  5. shailendra deshpande
    Replies:
    4
    Views:
    206
    Thomas 'PointedEars' Lahn
    Jun 16, 2008
Loading...

Share This Page