Computer Science Canada C++ Compile error with classes and objects. |
Author: | Craige [ Thu Dec 14, 2006 9:19 pm ] | ||
Post subject: | C++ Compile error with classes and objects. | ||
So, I'm still not great with C++, so I'm doing a bunch of pratice programs to get into the language. The one I'm doing now is a MadLibs generator/reader. I have just started it' so there is very little content to it, but I already have an error with the object I'm using: main.cpp:38: request for member `WriteLib' in `madLibsHandle()', which is of non-aggregate type `MadLibs ()()' Relivant code:
where Write lib is a public method of class MadLibs. What would cause the error here? |
Author: | wtd [ Thu Dec 14, 2006 10:15 pm ] | ||||
Post subject: | |||||
Having "write" or print" methods is poor practice in C++ anyway. Consider:
vs.
|
Author: | OneOffDriveByPoster [ Fri Dec 15, 2006 12:05 am ] | ||
Post subject: | Re: C++ Compile error with classes and objects. | ||
Looks like you are doing this:
Craige wrote: main.cpp:38: request for member `WriteLib' in `madLibsHandle()', which is of non-aggregate type `MadLibs ()()'
... and that your compiler ought to print the type better. |
Author: | md [ Fri Dec 15, 2006 1:00 am ] |
Post subject: | |
It would be nice to see all of the code; debugging from 1 error and ~4 lines of real code is quite hard. |
Author: | OneOffDriveByPoster [ Fri Dec 15, 2006 9:26 am ] | ||
Post subject: | |||
md wrote: It would be nice to see all of the code; debugging from 1 error and ~4 lines of real code is quite hard.
Looks like all the code you need is there though. The guy was pretty good about that.
|
Author: | md [ Fri Dec 15, 2006 9:41 am ] |
Post subject: | |
I don't see a declaration for MadLibs, which by the error seems to be being treated like a class with a member function WriteLib(); WriteLib) however is just declared as a function, not as part of a class. More code is definitely needed though, because even though you seem to have hit upon the right answer there could be other equally bad things in there as well... and I like looking at code ![]() |
Author: | wtd [ Fri Dec 15, 2006 9:52 am ] |
Post subject: | |
I'd wager a guess that md's right and there's a whole lot of funkiness going on here that we're just not seeing. But I could be wrong. Post all of the code! ![]() |
Author: | r.3volved [ Fri Dec 15, 2006 12:14 pm ] | ||||||
Post subject: | Re: C++ Compile error with classes and objects. | ||||||
Craige wrote: main.cpp:38: request for member `WriteLib' in `madLibsHandle()', which is of non-aggregate type `MadLibs ()()'
Relivant code:
Your declaration of your object doesn't need brackets unless you're passing something to the constructor. ex. Creating a string...
|
Author: | Craige [ Fri Dec 15, 2006 12:23 pm ] |
Post subject: | |
I'm at school right now, just about to go to Co-Op. I'll post the whole code tonight. The WriteLib method though is not neccessaraly a just a print function(method). It takes entire controll for the program, for that action, saving a bundle of code in main, and making things easier to read. What's wrong with that? |
Author: | wtd [ Fri Dec 15, 2006 12:33 pm ] | ||||
Post subject: | |||||
Well, you see, methods should be kept as absolutely simple as possible. It certainly sounds as though your WriteLib method is doing too much, though I won't be able to tell for sure until I see all of the code. Please don't take this too hard. It takes a long time to learn how to use objects. It takes even longer to learn when to use objects and how to use them correctly. ![]() As for:
If you are trying to declare an object of type MadLibs here, then you should know that C++ compilers will see this as a function declaration. To declare an object, and have it initialized by its default constructor, you should simply write:
|
Author: | Craige [ Fri Dec 15, 2006 7:15 pm ] | ||||||
Post subject: | |||||||
wtd wrote: If you are trying to declare an object of type MadLibs here, then you should know that C++ compilers will see this as a function declaration. To declare an object, and have it initialized by its default constructor, you should simply write:
That was the problem. Guess I read the book wrong ![]() I'll post the code anyway. Like I said, I just started it the other day, so it's just the base design, but here you go anyway: main.cpp
madlibs.h
I know my headers arn't organized like they should be. It's something I have to look into to see better how they work across files. |
Author: | wtd [ Fri Dec 15, 2006 7:27 pm ] | ||||
Post subject: | |||||
First off, a matter of style.
Now, there are a lot of issues with this code. A few: Please don't use C strings. C++ has a perfectly nice string class. You have the following:
Now, your MadLibs class has no constructors, default or otherwise. How do these variables get initialized? In all likelihood, they do not belong at this scope. Rather they should be locally scoped within a function. |
Author: | Craige [ Fri Dec 15, 2006 7:42 pm ] | ||||
Post subject: | |||||
wtd wrote: First off, a matter of style.
Now, there are a lot of issues with this code. A few: Please don't use C strings. C++ has a perfectly nice string class. While I respect your input on that matter, I would like to say that there is nothing wrong with the C style strings, nor the \n character. There are plenty of programmers who use them by choice in all their C++ programs. Quote: You have the following:
Now, your MadLibs class has no constructors, default or otherwise. How do these variables get initialized? In all likelihood, they do not belong at this scope. Rather they should be locally scoped within a function. The reason for that is because the class is just being designed. I hadn't wrote a constructor yet. I said when I posted that it was just in the beginning stages. I was just trying to get method definitions complete and check the compile to be sure it worked, and beings I wasn't planing on having any data passed to the constructor, it was not necessary for the compile, and I left it out for the time being. There will be a constructor later. |
Author: | wtd [ Fri Dec 15, 2006 7:44 pm ] |
Post subject: | |
Craige wrote: While I respect your input on that matter, I would like to say that there is nothing wrong with the C style strings, nor the \n character. There are plenty of programmers who use them by choice in all their C++ programs.
They are idiots. No, there's no more gentle way to put it than that. |
Author: | md [ Fri Dec 15, 2006 7:56 pm ] |
Post subject: | |
C-style strings are horrible. They are the single most common source of run-time errors and buffer over-run exploits. std::string provides such an unbelievably better string that there really isn't any good reason to be using a C string, no matter what. |
Author: | wtd [ Fri Dec 15, 2006 7:57 pm ] | ||||
Post subject: | |||||
To clarify, you should use endl instead of the string literal "\n". However, I am referring to things like declaring function parameters as:
rather than:
|
Author: | Craige [ Fri Dec 15, 2006 8:24 pm ] | ||||
Post subject: | |||||
wtd wrote: To clarify, you should use endl instead of the string literal "\n". However, I am referring to things like declaring function parameters as:
rather than:
Oh, yeah. Wasn't thinking about that. And while I still believe there is nothing wrong with C style strings, i have been switching everything over. |
Author: | OneOffDriveByPoster [ Sat Dec 16, 2006 12:07 am ] | ||||
Post subject: | |||||
Well, there is more than style to look at here. (Some more style too though). main.cpp
madlibs.h
|
Author: | Craige [ Sat Dec 16, 2006 12:46 pm ] | ||||||||||||||
Post subject: | |||||||||||||||
OneOffDriveByPoster wrote: Well, there is more than style to look at here. (Some more style too though).
main.cpp
Yes, I will be using char **argv. I'm going to use it to allow automatic opening of files, or anything else in the initial menu. Why is it**argv though? Quote:
So you mean use an infinate loop, and just check the command in the loop, and break if it's q (|| Q) Quote:
So I see. It leaves the enter character in the input buffer, doesn't it? Quote:
Can't use a switch statement if I'm going to check for 'q' || 'Q' in loop and break. Or atleast that check can't be part of the switch and would have to be an if. Maybe switch would be more suitable though. Quote: madlibs.h
Okay. Quote:
I'm switching it to std::string const &libname Quote:
Thanks for all the help you guys have been giving. I know the community I come from wouldn't have given a shit about all of this. It's good to talk to some people who do. |
Author: | md [ Sat Dec 16, 2006 1:03 pm ] | ||
Post subject: | |||
I see nothing wrong with char **argv, so long as you realize that it's read only and you are careful not to try reading from a null pointer. I also see nothing wrong with your loop control, though replacing it with a boolean do_exit type structure might be better, for example
Also see how a switch can be used, unless you call break execution will continue into the next case. |
Author: | Craige [ Sat Dec 16, 2006 1:08 pm ] | ||
Post subject: | |||
md wrote: I see nothing wrong with char **argv, so long as you realize that it's read only and you are careful not to try reading from a null pointer. I also see nothing wrong with your loop control, though replacing it with a boolean do_exit type structure might be better, for example
Okay. Maybe I'll do that then. I see how the do_exit would be cleaner. Quote: Also see how a switch can be used, unless you call break execution will continue into the next case. Yep, I know. |
Author: | wtd [ Sat Dec 16, 2006 1:23 pm ] | ||
Post subject: | |||
md wrote:
SOmething you may wish to consider is using a "continue" statement after the "do_exit = true;" statement. "break" will only exit the switch statement. Code after that but inside the loop will still be executed. One can, however, skip to the next iteration of the loop by using a continue statement instead. |
Author: | OneOffDriveByPoster [ Sat Dec 16, 2006 1:42 pm ] |
Post subject: | |
Quote: Yes, I will be using char **argv. I'm going to use it to allow automatic opening of files, or anything else in the initial menu. Why is it**argv though?
It's char **argv (or char *argv[], etc.) because it acts like a passed array of C strings. Each argument you pass in would usually be a separate string in this array. argv[0] is usually the name of your program executable. Quote: So you mean use an infinate loop, and just check the command in the loop, and break if it's q (|| Q)
Yes. Quote: So I see. It leaves the enter character in the input buffer, doesn't it?
Yes. It might be better to read the whole line too. That depends on how you want the input to be like though. Quote: Can't use a switch statement if I'm going to check for 'q' || 'Q' in loop and break. Or atleast that check can't be part of the switch and would have to be an if. Maybe switch would be more suitable though.
"goto" is not all evil. Consider it a labelled break. Saves you the problem that wtd pointed out. |
Author: | md [ Sat Dec 16, 2006 7:32 pm ] |
Post subject: | |
OneOffDriveByPoster wrote: "goto" is not all evil. Consider it a labelled break. Saves you the problem that wtd pointed out. I'm sorry... but you are dead wrong. Goto is stupendously evil. continue and break are only evil too but because they operate in well defined ways they are not so evil as to avoid using. Goto on the other hand is completely totally mind-blowingly evil. There is no reason ever to resort to spaghetti code, not ever no matter what. wtd pointed out a potential problem (one that I would consider very small, if everything happens in the switch anways) AND the correct solution to it. |
Author: | wtd [ Sat Dec 16, 2006 7:39 pm ] |
Post subject: | |
md wrote: OneOffDriveByPoster wrote: "goto" is not all evil. Consider it a labelled break. Saves you the problem that wtd pointed out. I'm sorry... but you are dead wrong. Goto is stupendously evil. continue and break are only evil too but because they operate in well defined ways they are not so evil as to avoid using. Goto on the other hand is completely totally mind-blowingly evil. There is no reason ever to resort to spaghetti code, not ever no matter what. wtd pointed out a potential problem (one that I would consider very small, if everything happens in the switch anways) AND the correct solution to it. Yet continue is really just a tamed form of goto. There are different kinds of goto. Local gotos are not evil, but nor should they be one's first choice. |
Author: | Craige [ Sat Dec 16, 2006 10:37 pm ] | ||
Post subject: | |||
Okay, I'm starting to work on the methods now. I've started with the WriteLib method, and I have created another one you will see in a few seconds. I once again have a compile error, due to type conversions (and one due to and object.) So, if I have a function defined to return std::string, how would I make it return a character from a variable? I tried doing a type cast on it, but that didn't work. It still gives me the compile error: madlibs.h:46: invalid conversion from `char' to `const char*' I also have a compile error: madlibs.h:79: request for member `HandleCharacter' in `this', which is of non-aggregate type `MadLibs*' Why would I be getting that on the this object? It's automatically defined. Here's the code:
|
Author: | md [ Sat Dec 16, 2006 10:44 pm ] |
Post subject: | |
instead of a cast use std::string(1, character); For more constructors/methods see http://www.cppreference.com/cppstring/ |
Author: | Craige [ Sat Dec 16, 2006 10:49 pm ] |
Post subject: | |
md wrote: instead of a cast use std::string(1, character); For more constructors/methods see http://www.cppreference.com/cppstring/
Oh wow, I didn't resize the string type was an object. Thanks. 1 down. |
Author: | OneOffDriveByPoster [ Sat Dec 16, 2006 11:48 pm ] |
Post subject: | |
Craige wrote: 1 down.
For the other: "this" is a pointer in C++. |
Author: | Craige [ Wed Dec 20, 2006 12:23 pm ] |
Post subject: | |
Okay, that fixed it. It compiles now. However, there is something wrong with the <ctrl> + d case of the switch in the method. It outputs a whole load of random stuff. Well, actually, the first time it seemed to be a bunch of Windows enviorment variables, but it's not now. Is it the way I'm settig &quit? I havn't done much with pass by refrence before, so I may be setting it wrong, or maybe even passing it wrong. Sorry for all the questions. I really want to pick up C++. I stated it before, but never went anywhere with it. This time I'm deturmaned to get a base in it, so I can move on with my programming. |
Author: | md [ Wed Dec 20, 2006 6:16 pm ] |
Post subject: | |
IIRC you can't handle ctrl+character like that. ctrl key combinations are used to send signals to programs, so some you won't get at all. Others I am not sure how you get them, but I'm fairly certain it's more complex then reading a character. Instead of just getting single letter inputs you could always get word inputs, that solves the need for ctrl+key inputs. Shorter (say two or three) letter inputs would also work. |
Author: | Craige [ Wed Dec 20, 2006 9:20 pm ] |
Post subject: | |
md wrote: IIRC you can't handle ctrl+character like that. ctrl key combinations are used to send signals to programs, so some you won't get at all. Others I am not sure how you get them, but I'm fairly certain it's more complex then reading a character.
Instead of just getting single letter inputs you could always get word inputs, that solves the need for ctrl+key inputs. Shorter (say two or three) letter inputs would also work. I know the ctrl + character key combinations are used to send signals to programs, and that is how I am using them. I am using them as quick 'variables' in the input. Also, they are read like that fine. Each combination is the same as a single key input. You just have to know which ASCII codes are which combinations. The ctrl + key combinations are ASCII values 1-31. So, provided you read them and convert them right, there is nothing wrong with that. |
Author: | Craige [ Wed Dec 20, 2006 9:41 pm ] |
Post subject: | |
Although, I didn't realize until now, I need to watch what key controls I use. ctrl + v is paste, so that should be changed. ctrl + n is generally new, but in a program like this, that won't be a factor, nor will the user expect ctrl + n to be the shortcut for new. |
Author: | OneOffDriveByPoster [ Wed Dec 20, 2006 10:08 pm ] | ||
Post subject: | |||
Craige wrote: Although, I didn't realize until now, I need to watch what key controls I use. ctrl + v is paste, so that should be changed. ctrl + n is generally new, but in a program like this, that won't be a factor, nor will the user expect ctrl + n to be the shortcut for new.
Assuming Windows, Ctrl+C and Ctrl+Z may be problematic. I agree that this looks problematic. If you are sticking to that though, you can try using this:
|
Author: | OneOffDriveByPoster [ Wed Dec 20, 2006 10:18 pm ] | ||||||||||||
Post subject: | |||||||||||||
What does the function return here?
While I would recommend against using "\n" exclusively, I would not recommend using "<< endl << endl".
Why not use "!complete"?
Oops. Maybe we should use std::getchar().
I would be very concerned if this compiled. The function does not ask for a pointer to bool. |
Author: | Craige [ Wed Dec 20, 2006 10:34 pm ] | ||||||||
Post subject: | |||||||||
OneOffDriveByPoster wrote: What does the function return here? Nothing, but I should sub something in. Quote:
While I would recommend against using "\n" exclusively, I would not recommend using "<< endl << endl". Okay. Quote:
Why no t use "!complete"? Why not use '!=' ? It's not like it's bad practice. != is just my style. Quote:
Oops. Maybe we should use std::getchar(). I know getch() and the conio library arn't standard, but that's not to be said they can't be used. I'm using getch because as far as I know, there is not unbuffered character input in C++ that is standard. I need the unbuffered input because of the quick key replacements for words and functions. Quote:
I would be very concerned if this compiled. The function does not ask for a pointer to bool. I don't remember if it did or not, but I don't have it as that now. |
Author: | md [ Wed Dec 20, 2006 11:01 pm ] |
Post subject: | |
ctrl+key presses are filtered from input and sent as signals through a different IPC method. I'm sure there is a way to change that, but by default things like ctrl-c will kill your program (or should... windows is dumb). |
Author: | wtd [ Wed Dec 20, 2006 11:19 pm ] |
Post subject: | |
If you're going to make your programs Windows-specific that's fine, though you'll probably find people here less than enthusiastic about your code. Also, you may find it useful, if you plan to go the Windows-specific route, to skip all of this conio crap and learn the Win32 API when you need low-level stuff, and C#/.NET for the high-level stuff. As for things like "!complete"... that was suggested because it more directly expresses the logic at work. It would be aided by a better variable name than "complete". A better variable name might be something like "is_complete", which includes not just a verb or state word, but also a word which indicates its boolean nature without resorting to something silly like Hungarian notation. |
Author: | Craige [ Wed Dec 20, 2006 11:41 pm ] |
Post subject: | |
wtd wrote: If you're going to make your programs Windows-specific that's fine, though you'll probably find people here less than enthusiastic about your code.
Who said I was going platform specific? That is not my intention at all. That is the furthest from it. Quote: Also, you may find it useful, if you plan to go the Windows-specific route, to skip all of this conio crap and learn the Win32 API when you need low-level stuff, and C#/.NET for the high-level stuff. See the above comment. Quote: As for things like "!complete"... that was suggested because it more directly expresses the logic at work. It would be aided by a better variable name than "complete". A better variable name might be something like "is_complete", which includes not just a verb or state word, but also a word which indicates its boolean nature without resorting to something silly like Hungarian notation. I see what you mean, but I have always found the != operator to be clearer. I don't know why. |