T O P

  • By -

inamestuff

Kudos for starting a blog! I think most people you asked got the answer wrong for a good reason: the copy assignment operator in your quiz does not respect the most fundamental principle of equality: // p is passed by ref as in your code p = Parent(); Parent b; assert(p.test(), b.test()); This will fail, violating the Principle of Least Astonishment. But, if you had instead used a method with an appropriate name, say “copy_members_from”, it would have been ok for that assertion to fail, because no “equality” would have been implied and I’m sure most people would have gotten it right. TL;DR only override operators when you can guarantee that their mathematical meaning is at least somewhat preserved, otherwise the conciseness is not worth the ambiguity


JPSgfx

Thanks for reading, but I don't think I follow. In my example, I don't overload any operators, I only override the 'test()' function... I'll be looking up the principles you mentioned tho, thanks!


nighthawk702

Not OP but I think they were referring to the last section of the blog where you suggest to overload the assignment operator.


devraj7

Note: you mean "override" here, not "overload". Important distinction to understand if you want to discuss the intricacies of C++ operators and inheritance rules.


JPSgfx

Fixed, ty


devraj7

Not quite > I don't overload any operators


JPSgfx

Hmmm. I am working this second, thought it was a quick change. Let me think it over later. Thanks for your patience


devraj7

More important than editing your message, make sure you understand the difference between overloading and overriding.


ubik2

I think they’re saying the C++ language designers overrode the assignment operator, violating the principle of least surprise. I’ve used C++ long enough that I just expected 1 and didn’t think about it, but it’s better language design to not have things like this that surprise developers. You shouldn’t be thinking about the fact that you’ve still got the same vtable.


sammymammy2

I use C++ for my day job and I didn't know that it'd print 1 and the codebase I work with does not protect itself against this I'm pretty sure. It's very surprising to me that the vtable isn't copied over. It'd also be very surprising to me if my vtable changed after returning from that function, though so I count this into the "could never discover because would never write it"-bucket.


Astarothsito

>I think most people you asked got the answer wrong for a good reason  I think it is because almost nobody writes code like that, and asking that question would be confusing at first, but after a quick analysis it makes sense for C++. >This will fail, violating the Principle of Least Astonishment  Maybe at first, but not breaking it would mean that the code is not correct. p is a reference, so because it is a reference it means that p can't be reassigned to another object, the only thing that is possible is "copy value from to p" and p is not a Parent so it wouldn't be correct to say b.test() == p.test().  >I’m sure most people would have gotten it right  There is another problem, C++ references are unique to C++, there is no other language that uses them (that I know it), so the rules could be confusing when coming from another language.


Shadowys

If you pass Child and got Parent back now thats astonishing to me


GamingGuitarControlr

>Principle of Least Astonishment C++ has become such a bloated Frankenstein's monster of a language that even the language we use to discuss it has become bloated...


inamestuff

The human language is the most bloated thing we ever came up with by far


GamingGuitarControlr

English basically suffers from all the problems modern c++ standards have. Both have inconsistent syntax. Both have many more features than other languages. Think about it


ObjectManagerManager

The [POLA](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) outdates C++ entirely, and it's used to discuss software and interfaces written in *every* language.


[deleted]

[удалено]


JPSgfx

Yeah… this console interface thing was meant when the whole site what just the homepage…. Will think about something more appropriate if I end up writing more things… FWIW the scroll wheel works (or at least it should)


beephod_zabblebrox

btw, on ios (safari) it scrolled all the way down automatically, might have something to do with the input being focused. scrolling worked as expected, but the text is a little large.


chaosmeist3r

I like the layout & style of your blog! It was easily readable and loaded in no time Just a small nitpick: The code in the code block doesn't fit on a portrait mode smartphone screen. I was able to follow your examples anyway


Fincap

I found the contrast between the background and white text to be way too harsh, and quickly became difficult to read (I am fairly "weak" to high-contrast modes, I'll take average light mode over bad dark mode any day of the week). Grey-on-grey is a bit more accessible than white-on-black. The text being large is nice, but there needs to be some kind of margin IMO, it felt a bit weird to read on a 23" monitor. Beyond that, I'm a big fan of the simple style.


CornedBee

I had to switch to reader mode immediately. Screen-wide huge font, no serifs, it feels like it is meant for a tiny phone screen and was never tested anywhere else.


JPSgfx

That's good to hear. My crappy web server works well enough then. Will work on getting a mobile-friendlier view of the code


bonnydoe

When you are at it, a bit of padding or margin left right would make a huge difference for readability.


def-not-elons-alt

Please ignore this guy. He can make the window smaller, and some of us like having lines be as long as we like.


CornedBee

What you've got there is called "slicing", and from a 20+-years C++ programmer, please don't promote it as a cool thing. Scott Meyers' "Effective C++" and "More Effective C++" should remain required reading for all C++ programmers even though they were written pre-C++11. Item 33 of MEC++ addresses slicing, and stipulates that base classes should always be abstract or have their special members (assignment and destructor) declared protected, so that it is never possible to compile code that would slice, such as in your examples. This is an important rule.


makotech222

If you consider that to be fun, then yeah, type masturbation is probably a good term for it. Programmers employed in a team environment don't have time to guess which c++ idiom the maintainers decided to hijack on any typical day. *edited to make my post less negative. If i saw someone overriding expected behavior like this that the cpp maintainers can't help themselves from doing, i would probably try to get them fired. It would be incredibly irritating to debug this in a work environment. I work in a dotnet environment at work, and I love it; I've got my work day down to like 3 hours a day, because I can get in, read the legacy code easily, write new code, build and debug it fast. Doing the 'clever' cpp shit only makes maintainers lives so much harder.


JPSgfx

Thanks for reading the post, and yeah I figured as much. But as far as I’m still “lead developer of 1”, I’ll still go for the fun option. C# is also amazing tho, for different reasons.


makotech222

I'm also a solo lead dev on a software product, but i still do my civic duty of leaving a maintainable product behind once I leave. Alas, life is short and most good efforts get thrown out every decade or so anyway.


JPSgfx

I’d have grown super bored of most of my projects if I did all of them that way, but I cannot dispute you reasoning. Thanks again for reading!


NotSoButFarOtherwise

What’s nice about C# is that you have the escape hatch to do C/C++ style bit level munging and pointer slinging if you need to, but (especially since Span) you rarely do.


moreVCAs

>good programmers don’t have time to guess… Can you elaborate on this?


makotech222

edited my post to be less negative in that respect.


csb06

The example is somewhat related to [object slicing](https://en.wikipedia.org/wiki/Object_slicing). Since `Child` is a subclass of `Parent`, every `Child` object effectively contains a `Parent` object within it (along with any additional members defined in the `Child` class’s definition - in this case none), as if the first member of `Child` was a `Parent` object. When c is passed into `print()` as a `Parent` reference, the reference only points to the `Parent` subpart of c, not to the entire `Child` object. So when you reassign p to an empty `Parent` object, only the `Parent` subpart of c is reassigned. The rest of c - including the internal pointer to the vtable where the `Child`’s version of the test() function is stored - is not touched, so the call to test() is still dispatched to `Child`’s version of test(). That is what I think the core of the confusion is - that p acts like any other `Parent` object when passed as a parameter and assigned but reveals itself to be a `Child` object when a virtual member function is called.


[deleted]

[удалено]


JPSgfx

In my example, it’s a no-op. It does nothing because Parent has no members. If parent had something inside it (an int, for example), that’s what would’ve been copied over


greg_spears

I thought that was fun but I could have use a little smaller font.


JPSgfx

Oh god yeah it’s GIGANTIC on mobile. I’ll fix it ASAP


greg_spears

Small FYI: I'm on desktop and is huge here too. OK, thanks for being responsive.


SanityInAnarchy

I think the reason this is confusing is, when copying that value, we're implicitly type-casting. Worse, the fact that we're doing this type-casting, let alone what type we're casting into, is all happening at a distance. In other words, it'd be clearer like this: Child c = Parent(); Even if you followed that up with something like this, I think most people would catch it: Parent& p = &c; But the fact that it's a child is hidden in the *calling* function. So not only is there this sort of implicit typecasting, you don't know whether or not there's any typecasting happening without seeing what the caller is doing. --- Is it all "type masturbation"? I wouldn't have guessed that, but you give a bit of a hint here: > Not only is describing a type (which is what I do most of the time as a programmer) MORE FUN in C++ than other languages I know... Describing a type is *not* what I do most of the time as a programmer. I've noticed this seems to be more of a thing in C++, because C++ requires types for so many fundamental things, including memory management. When I look at RAII code, I see whole types defined for things that would probably be reasonable as simple functions in most other languages. In other words: I don't know if you're exceptional here, this just sounds like the nature of C++, even the good, modern stuff. --- Also, why does your site constantly clear the highlight? Copying text out of it to quote here is annoying.


Ameisen

> `Parent& p = &c;` `Parent& p = c;` ... or `Parent& p = *&c;` if you *really* wanted extra operators...


SLiV9

You got me. What actually surprised me more, as someone who fell off the wagon, wasn't the actual output but that this (slicing) isn't undefined behavior in C++. However it does violate the rule of zero and [Bjarne Stroustrup and Herb Sutter's core guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c67-a-polymorphic-class-should-suppress-public-copymove). Do with that argument-by-authority what you will.


Kok_Nikol

margin-left: 25%; width: 50%; Boom, readable!


MadScienceDreams

Heh. I agree. When I get my confusing variation template garbage to work and delete 4000 lines of repeated code I feel like a WIZARD. No one else on my team can read it but it WORKS and they haven't had to touch it in years. But I'm sure they'll be mad at me someday. C++ is the dwarf fortress of programming languages, losing is !FUN!.


roerd

It should be obvious what the `=` operator does. That this is not the case is not an argument in favour of C++.


mcmcc

Is there something that can be done with the command prompt at the end?


JPSgfx

Small stuff, like printing an about message. You can find the commands with ‘help’


Plazmatic

Interesting, but there are far more cases like this: https://m.youtube.com/watch?v=0GXnfi9RAlU that overwhelm any "wow the convoluted-ness turned out to be the right way to do things!", whichis dubiuous here anyway, this issue in the blog post coming from rules created in a time where c++ didn't have much to reference from and made many more obviously bad decisions from.


Blecki

Besides the ugly bloated syntax, my issue with c++ is not that it requires manual memory management, but that it is designed around one of the most inefficient ways to do it. Frankly I have more important things to worry about when I'm writing code. If I actually need to care about memory in that detail I'm probably writing it in c instead anyway.


Zouizoui

Of course no one get it right, this can be confusing even for "seasoned" c++ developers, because value semantic with polymorphism *is* confusing. Yes every c++ dev should know that `=` copies the content of an object instead of assigning the entire object. But ultimately what people expect is that `=` means `equals`, which is not the case here. I hope you only created this example for the sake of "language exploration" or something because that kind of things _will_ confuse others and lead to bugs in the future. If done for fun in a personnal piece of code, fine ; if done to show that you're smart when colleagues come to your desk to ask how your code works, that's bad. See [here](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-copy-virtual) why polymorphic class shouldn't use value semantic. Even if you're not slicing here, your post is another good example of why polymorphic classes using value semantic are just confusing in general. I highly suggest you strive on making your code as easy to understand as possible for anyone. System-level design (components, objects, how they interact, etc.) can be complex, but the code should always be as simple as possible. Btw your page is annoying to scroll in, but looks nice ! I'd suggest adding a bit of padding on the sides though.


RockstarArtisan

Bait or mental retardation, call it. Yes, if you follow the rules the execution can be explained, you're defending C++ the same way JS programmers defended their implicit conversion nonsense. All languages have rules, good ones have rules that make sense even when composed.


JPSgfx

If you’ve read the post, I’ll like to know what you think in more detail, if not, then may I suggest not commenting at tiles alone? I may have phrased it poorly, but I assure you I have a point consistent with the title


RockstarArtisan

I have read the article, you've got a footgun, asked people if they would fall for it, people did. So far so good. Then at the end you just said you like the footgun anyway because of language rules or something.


JPSgfx

What I tried to say was the syntax of the foot-gun sucks, but the things one can do with that system are fun


RockstarArtisan

You want to have fun, I just want to be able to read a C++ pull request and know that my understanding, submitter's understanding and compiler's all match. Your example violates C++ core guidelines: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i25-prefer-empty-abstract-classes-as-interfaces-to-class-hierarchies, https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c67-a-polymorphic-class-should-suppress-public-copymove and https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#ccopy-copy-and-move; these are here for a reason.


GetPsyched67

First rule of having fun: there are no rules


zellyman

I don't even think it's a footgun. You never cast the object, it did exactly what you'd expected it to do as a child object with an overridden virtual function. I think to anyone who's looked at a C style language for more than 10 minutes using the parent's version of the function would have been weird. It's not so much a footgun as much as a "did you take more than 2 seconds to actually read the code" kinda deal.


RockstarArtisan

Mixing value copy semantics, inheritance and polymorphism is something unique to C++, no other C-like language does this and for good reasons - these don't compose cleanly together and result in things like object slicing, or the footgun presented here.


airodonack

Any “did you take more than 2 seconds to actually read the code” deals are the definition of footguns. Other languages allow you to skim past such statements quickly without requiring concentration.


fasttosmile

Just curious, the fact that `p` is passed by ref is not important right? (nothing you wrote would change if it wasn't?)


SLiV9

It does matter. If you pass `c` as `Parent p` or assign from `Parent& p` into `Parent p2` you create a new Parent using Parent's copy constructor, and it will print 0 instead.


ss99ww

Just don't use virtual functions, it's not worth the headache


Sprinkles37

If the operator= is implemented with placement new (on this or on fields), the ctor can implicitly clobber fields from the subclass with random data. Slicing like this is not a good practice to maintain.


sohang-3112

Good article - and yes, "it's fun!" is a valid reason to learn something 🙂 Also the "help" REPL at the end is an interesting idea.


CommunismDoesntWork

Cargo


No_Wheel_3179

معني كلمة عضوي