|
![](/i/fill.gif) |
Warp wrote:
> Right. So if it's possible to modify the data by having some wild pointer
> bug in the program, then it's not worth having compiler checks at all and
> just have everything public.
Well, sure, it's a little bit better. Not a whole lot better. As I said,
it's a sliding scale.
For me, not sufficiently important that it's worth worrying about. The fact
that I can use a pointer to step through the data of a class with private
members is no better than the fact that I can iterate over the members of a
Python instance by groping thru the hash table that implements it.
>> Sure. What about a naming convention that "comes with the language"? I.e.,
>> not just a naming convention you made up, but one in common for every single
>> program written in the language from day one?
>
> By that reasoning you could argue that C is an object-oriented language.
> After all, you can get OO'ish behavior if you follow certain coding
> conventions.
Well, that's what I'm asking. I find it odd that "encapsulation" covers
exactly everything that C++ does, no more no less.
>>> So yes, it's much better if the compiler tells the user he is accessing
>>> what he shouldn't.
>
>> I agree it's better. But since you seem to like binary definitions, and you
>> don't like me saying "C++ has a little bit of encapsulation but not much",
>> I'm curious if you think that (say) Python has encapsulation, given that
>> everyone knows that names with _ are private to the class they're in?
>
> How is it encapsulation if everything is public?
"""
A language construct that facilitates the bundling of data with the methods
operating on that data.
"""
Again, it's the definition you pointed to.
> That actually contradicts what you said originally. Originally you said
> that C++ has *no* encapsulation. Clearly you were drawing a clear line
> somewhere.
It has so little encapsulation (in the "restricting access" part of the
definition) that it might as well not have encapsulation. If you're talking
about the data hiding part, I'd say that unsafe languages don't have that.
Many have the other "bundling data and code" kind of encapsulation.
In other words, I find that marking something as "private" doesn't give
significantly more protection to private data than marking something with an
underline does in Python, in practice. In practice, both are trivial to get
around, accidentally or on purpose.
>>>> In contrast, C++ has well-defined mechanisms for bypassing the encapsulation
>>>> that are used as a normal part of programming in that language.
>>> Actually it doesn't. You can read the binary representation of an object
>>> in memory, but the standard gives no guarantees as to which byte means what.
>
>> I don't believe that's true. It certainly wasn't in C.
>
> What wasn't in C?
That the standard said there's no guarantees as to which bytes mean what or
how things are laid out in memory.
> As for the C++ standard, it does certainly not give any guarantees about
> the bit representation of objects in memory. It's implementation-defined.
Funky. I was pretty sure at least unsigned had a guarantee that they were
represented in two's complement binary (e.g., that the bit pattern 0x11 was
the integer value 3).
>>> The memory layout of objects is completely implementation-defined
>> Nonsense. Arrays are contiguous.
> Arrays are not objects. Arrays are a collection of objects.
Yeah, I figured that would be your answer.
>> The elements of a structure are all between
>> &x and &x + sizeof(x).
>
> No, they aren't. The standard doesn't specify how much padding there may
> be between struct elements. The compiler can add as much padding as it wants
> (or none at all).
That doesn't invalidate the formula. I didn't say there was nothing else there.
> Also, the standard doesn't guarantee that the first member of a struct
> starts from the same memory address as the struct instance itself. (In
> practice this can actually differ if the struct has virtual functions.
> In that case the pointer-to-struct-instance will not point to the first
> member of the struct. There will be some implementation-dependent vtable
> pointer there instead.)
I didn't say that it did.
Wasn't one idea of C++ was that structs without vtables would layout the
same way as C structures?
> If a member is private, you have no safe, portable way of accessing it
> from the outside.
Right. But I'm not talking about the safe parts. :-)
In any case, yes, there is, because the class can return a pointer to the
private variable. You might say "that means it's not private any more", but
it's still accessing the program's private variables. (Uh, that *is* legal
in C++, right? Returning an int* that points to a private instance variable?
If not, then color me suitably impressed. :-)
>> There's lots of guarantees. And I'm pretty sure that
>> if you have "struct x {int a; int b} y;" that the standard guarantees
>> &b > &a.
>
> Probably, but if a and b are private, you have no portable way of getting
> an address to them. You don't know the offset.
You do inside the class. :-) And besides, I'm just disputing your assertion
that the language makes no guarantees about the layout of data.
I've worked with languages that make *no* guarantees about the layout. Where
the lowest bit of *every* integer was 1, regardless of its value. Where
pointers have reference counts and type flags in the high bits. Stuff like that.
Trust me, C++ makes some guarantees. :-)
>> Positive integers are represented in twos-complement coding.
> I'm not completely sure the standard guarantees that.
>
>> Unsigned integers occupy the the number of bits indicated by multiplying
>> sizeof(unsigned) by bits_per_char or whatever the appropriate #define is.
>
> Well, duh, because sizeof(type) is *defined* as telling the amount of
> bytes that the type requires.
Yes. And then you multiple by bits_per_char to find out the range, which
means unsigneds don't have padding in the middle, for example.
> That still doesn't help you accessing private data of an object portably.
That's not what I'm discussing at this point. Besides, you can *access* them
portably. You can't *interpret* them portably, perhaps, if the structure is
complicated enough.
>> Now, if you're going to argue those guarantees don't count, Ok.
>
> Don't count to what? The issue was whether it's *well-defined* to break
> encapsulation in C++. Your own words.
Don't count the guarantees I listed. You said "C++ makes no guarantess on
layout" and I listed a bunch it makes.
And breaking encapsulation is portably accessing private members from
outside the class. Which I can certainly do using memcpy for example.
> It's not well-defined. You can try, but the results are not guaranteed.
So write(out, &xyz, sizeof(xyz)) where xyz is a class or struct with private
members might actually crash?
memcpy(myarray[0], myarray[1], sizeof(myarray[0])) isn't well-defined?
There's no meaning for that statement when myarray[0] is a struct with
private members?
Regardless of whether you know which private variable is laid out where,
you're still "accessing private variables" in ways that more secure
languages disallow.
> You mean C++ is causing problems there?
Oh, you wouldn't believe. Not C++ per se, but unsafe languages in general,
poorly organized and badly documented.
> I suppose I should consider myself lucky in that I get to work in
> projects where I don't have to go fixing existing code made by incompetent
> C++ programmers...
Yep. Well, honestly, the whole development chain is screwed. Not only is the
code buggy, but the authors are unwilling to fix it, describe it, document
it, or really take any responsibility at all for its sorry shape.
--
Darren New, San Diego CA, USA (PST)
The question in today's corporate environment is not
so much "what color is your parachute?" as it is
"what color is your nose?"
Post a reply to this message
|
![](/i/fill.gif) |