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

D

Don Bruder

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?
 
W

White Wolf

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
 
M

Mike Wahler

Don Bruder said:
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
 
A

Alexei Betin

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 said:
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 - (e-mail address removed) <--- 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>
 
A

Alexei Betin

Kevin Goodsell said:
<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...
 
C

Christopher Benson-Manica

Alexei Betin said:
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...?
 
K

Kevin Goodsell

Christopher said:
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
 
A

Alexei Betin

Christopher Benson-Manica said:
Alexei Betin <[email protected]> spoke thus:




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
 
C

Christopher Benson-Manica

Mike Wahler said:
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...)
 
K

Kevin Goodsell

Christopher said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top