|
litghost posted:What does it do?
|
# ? Aug 2, 2009 22:20 |
|
|
# ? Jun 13, 2024 03:55 |
|
dustgun posted:Nothing, that's the beauty of it. The function-try-block doesn't do anything, but the throw-expression inside the conditional-expression does.
|
# ? Aug 2, 2009 23:01 |
|
litghost posted:What does it do? The only thing I'd expect it to do is emit a diagnostic about 'mF' at compilation time.
|
# ? Aug 3, 2009 09:40 |
|
hey guys C/stdio question. there is this function:code:
Or at least that's what supposed to happen. I get a segmentation fault on a machine with Ubuntu on the fread line after it tries to read the 10th byte (refers to iofread.c file in line 43 I think, but the machines didn't have the source for the stdlib they use). I don't get it because it reads in the first file in it's entirety just fine. The weirder thing is it works fine on my Macbook Pro/C2D/OSX-1.5.7. ShinAli fucked around with this message at 15:19 on Aug 5, 2009 |
# ? Aug 5, 2009 05:11 |
|
ShinAli posted:hey guys C/stdio question. there is this function: No, it doesn't. It completely ignores the passed in stream, attempts to read a single byte from an undefined stream, and returns a byte which may be the result of such a read, but may just be undefined as well because the read isn't checked for success. ShinAli posted:Two different FILE pointers are used with this function. The first file is read in and stored into memory, No, the passed-in file pointer is not referenced. At all. ShinAli posted:then it's file pointer is closed. fclose is not called in that function. ShinAli posted:The second file is fseek'd to the end, got the file size using ftell, then I did another fseek to the beginning. The file is read intermittently until I get to the end of file. What the hell are you talking about? ShinAli posted:Or at least that's what supposed to happen. I get a segmentation fault on a machine with Ubuntu on the fread line after it tries to read the 10th byte (refers to iofread.c file in line 43 I think, but the machines didn't have the source for the stdlib they use). I don't get it because it reads in the first file in it's entirety just fine. The weirder thing is it works fine on my Macbook Pro/C2D/OSX-1.5.7. It is pretty weird that you got this code to work fine anywhere, yes.
|
# ? Aug 5, 2009 05:26 |
|
ShoulderDaemon posted:No, it doesn't. It completely ignores the passed in stream, attempts to read a single byte from an undefined stream, and returns a byte which may be the result of such a read, but may just be undefined as well because the read isn't checked for success. Sorry, typo. There was supposed to be a lfi = f after FILE * lfi. As for the rest of your comments, I was trying to express what happens in general in the program and how the function is used with it. But you can chillax, I figured it out. For some reason this guy doesn't know how to handle his pointers and the FILE pointer got decremented somehow. ShinAli fucked around with this message at 23:18 on Aug 5, 2009 |
# ? Aug 5, 2009 15:26 |
|
Contains Acetone fucked around with this message at 18:10 on Jun 24, 2020 |
# ? Aug 8, 2009 07:08 |
|
Contains Acetone posted:Could someone explain to me why this doesn't work they I would expect it to? http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9 (Yes there is a good reason for this, but that would be a short essay, and . For people playing the home game, consider what would happen if you had Parent::foo(int) and Child::foo(char).) Avenging Dentist fucked around with this message at 07:13 on Aug 8, 2009 |
# ? Aug 8, 2009 07:10 |
|
Contains Acetone fucked around with this message at 18:09 on Jun 24, 2020 |
# ? Aug 8, 2009 07:22 |
|
Contains Acetone posted:It would call foo(int) when passed in int and foo(char) when passed a char Sorry, try again!
|
# ? Aug 8, 2009 07:31 |
|
Contains Acetone fucked around with this message at 18:09 on Jun 24, 2020 |
# ? Aug 8, 2009 07:41 |
|
Contains Acetone posted:I don't understand. Why on earth does it do that? Why does the compiler think it's a good idea to pass a char to a function that requires an int? Because a char is an integral type and can be converted to an int using the integer promotion rules defined in the ISO C Standard, §6.3.1.1 and the ISO C++ Standard, §4.5. Contains Acetone posted:This situation is different from the one I posted about. I want the parent class to have one method A which uses virtual method B, and then use the child's implemented version of that method B from within the parents method A. It's not a different situation, it's the exact same situation, but the C++ standard wasn't about to make the subclass overloading rules any more complicated by requiring hiding to occur only in the cases where it was absolutely necessary. Contains Acetone posted:Redeclaring the function in the children and calling the base method as suggested in the reference you posted has fixed my problem though. Actually, I didn't. I (indirectly) suggested using the using syntax. Contains Acetone posted:EDIT EDIT: Auto promotion sounds like a bad idea Basically every language with multiple integral types does this because it's a pain in the rear end to write overloads for all of (char, short, int, long, long long) and unsigned variants. In general you should not get mad at the language because it does something you neglected to learn about. Avenging Dentist fucked around with this message at 07:54 on Aug 8, 2009 |
# ? Aug 8, 2009 07:46 |
|
Contains Acetone fucked around with this message at 18:09 on Jun 24, 2020 |
# ? Aug 8, 2009 08:03 |
|
Contains Acetone posted:Can you give me an example of why this is necessary that wouldn't be fixed by simply checking the inputs (ie, not passing a char when an int is required)? A char is, and always will be, a perfectly acceptable alternative to an int. If you prefer, consider an int and a long. The issue here is that a virtual member function provides a contract to the programmer that any call to it from the base class will be the same as calling it from the subclass. Overloading in a subclass is a violation of that contract, so C++ expects you to import the base class function into the subclass's namespace as a way of saying "yes I really mean for you to do this". The hiding rule obviously causes some false positives (non-virtual functions, functions with different arities), but it's better to keep rules as simple as possible, provided they don't allow for dangerous things to happen without the programmer being fully aware. Better to issue a compiler error than to make sure the programmer knows what's going on. Unfortunately, GCC's error reporting is poo poo, and it should be explaining what's going on.
|
# ? Aug 8, 2009 08:28 |
|
I think the argument is pretty weak for instance members, to be honest. Both unexpected overloading and unexpected hiding can cause surprises, but in practice people generally know which names are going to be overloaded. And if you overload functions based on types which are implicitly convertible, well, now you're just asking for it. Static functions make a more compelling argument, because qualified lookup still finds things from base classes, so it's impossible to say "no seriously, just the one declared right there". It's quite common for, say, factory functions to just append more parameters to the base class's version, like so: code:
|
# ? Aug 8, 2009 20:50 |
|
rjmccall posted:I think the argument is pretty weak for instance members, to be honest. Both unexpected overloading and unexpected hiding can cause surprises, but in practice people generally know which names are going to be overloaded. Things that work but shouldn't are universally more dangerous than things that don't work but should.
|
# ? Aug 8, 2009 20:52 |
|
Avenging Dentist posted:Things that work but shouldn't are universally more dangerous than things that don't work but should. I agree, but what's your point? Both ways you could decide this question enable "things that work but shouldn't". You yourself just provided an example where hiding methods instead of overloading them caused unwanted behavior with no diagnostic possible.
|
# ? Aug 8, 2009 21:41 |
|
rjmccall posted:You yourself just provided an example where hiding methods instead of overloading them caused unwanted behavior with no diagnostic possible. Actually my example was kinda lovely, since the "using" is superfluous*. The issue is that without hiding, you end up calling out to strange places based on conversion/default-argument rules, and the standards writers felt it made more sense to isolate lookup of overloads to a single class. * It does change the behavior when you call foo with an int though. Avenging Dentist fucked around with this message at 21:54 on Aug 8, 2009 |
# ? Aug 8, 2009 21:47 |
|
Avenging Dentist posted:That's because I explicitly imported the base class member function into subclass. Otherwise, you'd absolutely get a diagnostic. Bah, I'd forgotten which way you had it. code:
UNEDIT: Moving to its own post. rjmccall fucked around with this message at 21:58 on Aug 8, 2009 |
# ? Aug 8, 2009 21:53 |
|
rjmccall posted:Bah, I'd forgotten which way you had it. The specifics of my example were stupid, but see above. ^^^
|
# ? Aug 8, 2009 21:54 |
|
I can definitely understand why the committee designed it that way; I just think it was a mistake. Non-static member overload resolution is already a fiendishly complicated and subtle process; hiding doesn't really make it any easier. Hiding does make it easier for humans to reason about in cases where the programmer hasn't explicitly brought base-class operations into scope, but it turns out that that's pretty uncommon for non-static members, because programmers don't generally want subclasses to lose operations from their base classes. So all it adds is more required boilerplate. Another perspective: suppose you used a rule where all base class instance methods were candidates for instance-method overloading. Would the choices of that rule really be more complicated to explain than, say, the results of argument-dependent lookup?
|
# ? Aug 8, 2009 22:16 |
|
rjmccall posted:I can definitely understand why the committee designed it that way; I just think it was a mistake. Non-static member overload resolution is already a fiendishly complicated and subtle process; hiding doesn't really make it any easier. (With hiding) it's not really any more complicated than any other kind of overload resolution. One of the more difficult sticking points in a non-hiding subclass overriding system would be the behavior of member functions with default arguments. In terms of overload resolution, they are essentially N+1 separate functions, where N is the number of default arguments. Overriding various subsets of that (but not others) in a subclass would be complicated as poo poo. rjmccall posted:Hiding does make it easier for humans to reason about in cases where the programmer hasn't explicitly brought base-class operations into scope, but it turns out that that's pretty uncommon for non-static members, because programmers don't generally want subclasses to lose operations from their base classes. The subclasses aren't losing any functionality whatsoever. You just need to use qualified-ids to look up hidden base-class functions. rjmccall posted:Another perspective: suppose you used a rule where all base class instance methods were candidates for instance-method overloading. Would the choices of that rule really be more complicated to explain than, say, the results of argument-dependent lookup? Yes because default arguments are a pain even when you're not dealing with selective overriding of subsets of their possible lookup contexts.
|
# ? Aug 9, 2009 01:28 |
|
Avenging Dentist posted:Overriding various subsets of that (but not others) in a subclass would be complicated as poo poo. Only from an implementation perspective, I think, and it's not like this would even make the top five list of C++ Features That Compiler Writers Hate Implementing. From a user perspective, I don't think it's any different from having k different functions (all with different argument counts) that you wanted to selectively override. Currently, if you want to keep any of the overloads from a base class, you either import all of them into scope and let the overload-resolution mechanism sort it out, or you write explicit proxies for the ones you want to keep. In a no-hiding world, if I wanted to selectively override certain overloads from a base class, I would... write explicit overriding methods, possibly using a method with default arguments. If I didn't want to override a specific (intermediate) default-argument instance, I could write an explicit proxy for it that called the base class's implementation. I don't see how this is inherently more difficult or more complex than what C++ now requires. Avenging Dentist posted:The subclasses aren't losing any functionality whatsoever. You just need to use qualified-ids to look up hidden base-class functions. Weren't you just saying that implicit overloading would change a virtual method's contract by modifying behavior under substitution? So does taking entire methods out of default consideration. I mean, yes, the functionality isn't lost — I could explicitly qualify the method name, or I could cast the implicit argument to the appropriate base, or I could add a proxy, or I could use ghetto overloading and encode parameter types in the method name to avoid the entire issue. But the problem remains that programmers can break working code by adding overloads in subclasses, which no-one expects who hasn't deeply internalized the C++ standard. Avenging Dentist posted:Yes because default arguments are a pain even when you're not dealing with selective overriding of subsets of their possible lookup contexts. A well-designed default arguments implementation would not be seriously challenged by any of this.
|
# ? Aug 9, 2009 07:55 |
|
rjmccall posted:But the problem remains that programmers can break working code by adding overloads in subclasses, which no-one expects who hasn't deeply internalized the C++ standard. Neither solution is clearly "right" in all cases. The standards writers chose the one that gives you the most flexibility (don't do this by default, but you can do it explicitly if you want), which is pretty much in keeping with C++'s philosophy. This also has nothing to do with knowledge of the C++ standard and everything to do with GCC's shameful diagnostics. A good compiler should tell you the parts of the standard that you need to know; that's what warnings/errors are for. The fact that GCC fails to provide decent diagnostics 75% of the time is another reason I'll be glad when that project finally dies. rjmccall posted:A well-designed default arguments implementation would not be seriously challenged by any of this. Ok, you're the one making the assertion that this is easy. Write a proof of concept or a spec for it. Avenging Dentist fucked around with this message at 17:53 on Aug 9, 2009 |
# ? Aug 9, 2009 17:44 |
|
Looking online in more depth, one of the main reasons people cite for this is what happens not when looking at a static piece of code, but what happens when you change code (esp. base classes)? alt.comp.lang.learn.c-c++ discussion D discussion of why they felt they should/should not keep hiding
|
# ? Aug 9, 2009 18:02 |
|
Avenging Dentist posted:A good compiler should tell you the parts of the standard that you need to know; that's what warnings/errors are for. The fact that GCC fails to provide decent diagnostics 75% of the time is another reason I'll be glad when that project finally dies. I think everyone agrees that GCC's diagnostics are poor. Now, clang's diagnostics don't check whether there was a hidden match, either, but I'll make a note to fix that. Avenging Dentist posted:Looking online in more depth, one of the main reasons people cite for this is what happens not when looking at a static piece of code, but what happens when you change code (esp. base classes)? The D thread brings up a lot of examples where changes to a base class can break a subclass without diagnostics. You will note that all of their real-world examples don't involve name hiding at all; it's only the constructed examples that do. Basically, inheritance inherently involves tight coupling, but most people don't think of it that way. If people were actually serious about this safety issue, they would require virtual methods to be redeclared in all subclasses; but of course people are not actually serious about it. But yes, there are certainly dangers both ways. Avenging Dentist posted:Ok, you're the one making the assertion that this is easy. Write a proof of concept or a spec for it. [basic.lookup.argdep]p3. Change "Let X be the lookup set produced by unqualified lookup" to "Let X be the lookup set produced by unqualified function lookup". Insert a new section, [basic.lookup.unqual-function]: [basic.lookup.unqual-function] Unqualified function lookup 1. This section is used only for the lookup of an unqualified name used as the postfix-expression of a function call. 2. Lookup proceeds as specified in [basic.lookup.unqual], except that if the result set includes a non-static member function declared on a class A, all non-static member functions with that name declared on base classes of A (whether direct or indirect) are added to the result set.
|
# ? Aug 9, 2009 20:17 |
|
rjmccall posted:I think everyone agrees that GCC's diagnostics are poor. Now, clang's diagnostics don't check whether there was a hidden match, either, but I'll make a note to fix that. This is because clang's support for inheritance is still pretty limited. Until a few days ago, it didn't even allow for qualified-id lookup of members. Clang still has a long way to go before it's a real C++ compiler.
|
# ? Aug 9, 2009 20:35 |
|
I'm trying to get a simple test C++ program working, but I'm loving something up badly. I've got two files that look like this: in Foo.h code:
code:
|
# ? Aug 11, 2009 22:36 |
|
User0015 posted:
You didn't explain what the problem was (What's actually going wrong?) But at a quick glance you're not treating "bar" as a pointer in Foowork() (use -> and not .). And naming a function "get_"-something when it's a setter is just weird. Edit: Oh and if you actually want to call Barwork() in Foo.h, Bar needs a full definition and not just a forward declaration. Vinterstum fucked around with this message at 22:43 on Aug 11, 2009 |
# ? Aug 11, 2009 22:40 |
|
That's exactly what I want it to do. If the problem is in the definition, how would it look? I tried a simple definition but it reported the same error(s) regardless. There's a bit more to it, or I'm omitting something obvious.
|
# ? Aug 11, 2009 22:49 |
|
User0015 posted:That's exactly what I want it to do. The definition of class "Bar" is the lines of code you have in Bar.h. Without that, the compiler can't figure out what you're trying to do in Foo::Foowork. Just include Bar.h on the top of Foo.h (or better, move the definition of the Foowork() function to a .cpp file instead of a header file, so other files can include just Foo.h without getting Bar.h included in the bargain). I.e. Foo.h just declares the function as "void Foowork();", and Foo.cpp contains the actual definition as "void Foo::Foowork() { bar.Barwork();". But for the future: It helps if you actually paste the error you get.
|
# ? Aug 11, 2009 22:56 |
|
I think the problem is that you don't have a main function!
|
# ? Aug 11, 2009 23:00 |
|
Avenging Dentist posted:I think the problem is that you don't have a main function! I don't need no stinkin' main. I just omitted it. If you think it would help I guess I could paste it? It's...a line long? Two?
|
# ? Aug 11, 2009 23:07 |
|
User0015 posted:I don't need no stinkin' main. Well, if you want help for something like this, you should probably post the whole thing.
|
# ? Aug 11, 2009 23:10 |
|
The original program would be to large to post. I just set up this simple program to show exactly what the issue was. I don't think the problem is related to anything in main. Does this code look like it should work, so you're asking for additional code because the problem is elsewhere? I threw this little example together so you (hopefully) wouldn't have to dig through extraneous code. edit - I did forget to throw in the error message. It reads: "In member function 'void Foo::Foowork()' 'Barwork' has not been declared. request for member of non-aggregate type before '(' token. " Both errors on line 5 in Foo.cpp which is simply "bar.Barwork();" If it's supposed to be bar->Barwork(); , the error reads as: "invalid use of undefined type 'struct Bar' " Line 6 in Foo.h reports error "forward declaration of 'struct Bar' " which is the line "Class Bar;" User0015 fucked around with this message at 23:26 on Aug 11, 2009 |
# ? Aug 11, 2009 23:14 |
|
You're posting excerpts that are obviously excerpts, and you're not telling us what errors you're getting, how you're running things, or really anything at all besides "something is wrong". Therefore you're forcing us to extrapolate your entire program structure and guess the problem. The problem is probably that you don't understand header files, but we really can't be sure, because you've left out so much crap.
|
# ? Aug 11, 2009 23:25 |
|
Alright then, I'll just post everything. Foo.h code:
[non-empty]Foo.cpp code:
code:
code:
|
# ? Aug 11, 2009 23:33 |
|
Looks like you are defining Foo::Foowork for a second time in foo.cpp for no real reason and also you are calling methods on Bar instances while only having a forward-declaration available, you need a proper definition of the class for anything but having a pointer to it that just sits there.
|
# ? Aug 11, 2009 23:36 |
|
User0015 posted:edit - I did forget to throw in the error message. It reads: "In member function 'void Foo::Foowork()' 'Barwork' has not been declared. request for member of non-aggregate type before '(' token. " Both errors on line 5 in Foo.cpp which is simply "bar.Barwork();" Try implementing both of the things I suggested at once (both include Bar.h in Foo.h (or move the definition to the cpp file and include Foo.h in that one), and change the . to ->), instead of just one of them at a time. Vinterstum fucked around with this message at 23:40 on Aug 11, 2009 |
# ? Aug 11, 2009 23:36 |
|
|
# ? Jun 13, 2024 03:55 |
|
Vinterstum posted:Try implementing both of the things I suggested at once (both include Bar.h in Foo.h (or move the definition to the cpp file and include Foo.h in that one), and change the . to ->), instead of just one of them at a time. Well, I just tried this. Foo.cpp code:
Bar.h - added "friend class Foo". It compiled. Doesn't work, but it compiled. That's always a good start.
|
# ? Aug 11, 2009 23:49 |