- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Ugh, I used to use that sort of just-in-time allocation myself, until I got sick of running into issues like this. Now I prefer to just allocate in advance for simplicity's sake, though I can understand you not wanting to re-engineer the system for one loop.
In your case I would probably have gone for the having two methods "getSafeButt()" and "getScaryButt()" idea though. At least it forces other coders to consider what they're doing, and stops them from actually writing to the value in any way they please.
As a side note, MSVC++ 8 (and maybe other compilers as well) have Link Time Code Generation, which allows the linker to selectively inline functions for you and make other optimizations between different obj files. This allows the rule of never inlining code defined in .cpp files to be bypassed. I guess theoretically you could inline a function defined in a cpp file, so long as it's only ever called from with that cpp file, though that sounds like quite an ugly thing to do.
Admin
Admin
It might not be legal but it seems like it would certainly work. I'm not sure about the #define of protected back to protected though, you may have to do something like:
On the performance issue, if you were really that paranoid about squeezing the best out of every CPU cycle you wouldn't use C++ (or any other OO language), you'd write in C or Asm. And anyway, for this kind of application I'd be willing to bet that the real performance bottleneck in the data access layer rather than some (potentially) notional function call overhead.
Admin
#undef protected
Admin
I hate, hate, hate it when job interviewers ask that one and I give a poorly articulated answer that they try to misinterpret as me thinking that it's "about security". I'm not that incompetent. Just need to learn me some words n'stuff.
Admin
As I said, "the runtime usually sees those trivial calls and inlines them". I meant "runtime" to mean the "runtime environment" which would be the Java VM or whatever C# uses. In C++ inlined functions have to be in the same Translation Unit for the compiler to optimize them. It all has to be done at compile time.
Admin
}
HotMama baby = new HotMama();
// baby got back
Admin
It is similar to something I have to do in my software to make it work with a braindead library. The library authors could of course choose to not use C++-keywords in their header files, but nooo, that would be too difficult. Instead I get a release note saying that "this software cannot be used with C++". Here is how I deal with their stupidity:
extern "C" { #define private Private #define class Class #include "xxxxxx.h" #undef private #undef class }
Admin
The problem with unenforced conventions is that they tend to get ignored.
Admin
Un-diciplined programmers can just as easily screw up the public interface by adding parameters to functions, changing their names, etc, as they can by accessing and changing 'private' properties.
If the source code is available, there's no such thing as 'enforced' conventions.
Admin
"Sometimes accessor functions really are too slow. In that case making the fields public and asking the callers not to modify them seems completely reasonable to me."
With any reasonable compiler, it will be trivial to make accessor functions precisely the same speed as directly accessing the member variables. The generated code should be precisely the same in both cases.
Now you might theoretically have some case where for one reason or another an accessor function has a speed penalty you cannot get rid of and you can show that this penalty is significant. But it's extremely hard to imagine how that could happen for every member of any realistic class.
This idiot probably heard somewhere that accessor functions were slow (plus, they take a few seconds to write) and so he doesn't ever use them.
That's a WTF.
Admin
"In C++ inlined functions have to be in the same Translation Unit for the compiler to optimize them. It all has to be done at compile time."
Really? What section of the standard says that?
Assumptions like that get people into big trouble when new versions of the compiler support optimizations that they didn't think were possible, practical, or likely when they wrote the code.
Admin
Admin
Soooooo, you've been a developer for what 6 months? a year?
To answer your question, yes implementation changes are quite common; and private/protected/public decisions are a cornerstone of good class design. If you don't understand this you might want to retake a few basic programming classes....
My apologies if my sarcasm detector is misconfigured....
-Me
Admin
And if you're writing a framework or library that will be used by dozens, or maybe thousands of client applications, you do NOT want to break half of them when you change implementation details. Telling them it's their own fault because they didn't follow convention is hardly a better solution than having the problem not occur at all, now is it?
Admin
All this talk about #define private public, and no-one mentioned the legal way to access a class's private variables in C++?
Admin
Huh. Works like a charm. If I ever see anyone do that to one of my header files, I'm going to throw the book at them--by which I mean the C++ standard, and aim for the head.
Admin
In many programming languages, I really wish there was some way to do public and read only. It wouldn't hurt to have direct access to some status variables, but have the compiler refuse to modify them when writing from outside the object.
Function results are one-way, why can't there be keywords to make object properties (status) act only in one direction?
Admin
One thing I would like to point out, that has been commented on, is that these functions are 'Safety Critical'.
We can't determine what the software does or controls, but when I hear safety, I think of protecting people from hazards.
If this is a medical device, and changing the variables could effect something important, like say the amount of radiation emitted by a scanner, I would really like it to be impossible to 'accidentally' change the variables.
And yes, people should read the comments and follow them, but people forget and make mistakes. Thats why we have seatbeats, because at some point something may go wrong.
Having the compiler help you out by reminding you "Error: MegaWatts cannot be accessed, variable is Private" seems like a wonderful idea.
~Tilendor
Admin
Besides, you already gave a perfectly good solution: return values are one-way, so you just use a getter method. In C# you have exactly what you want, implemented that way. And before you mention performance please go re-read the Tao of premature optimization.
Admin
Absolutely correct. When safety-critical software fails, someone could die. Whoever programmed this into a safety-critical application, and then left a smoking-gun comment in the code obviously is not worried about a code audit from an outside regulatory agency -- or a subpoena from a pack of lawyers.
Admin
It's not that difficult, really. C++ might have the world's most extreme set of syntactic warts (see various Boost and templating meta-programming), but it does make sense if you stare hard enough.
Private means private. Public means public.
Protected means ... well, I have a problem with protected, although there are some very restricted cases where you might want to use protected inheritance rather than the other two. I wouldn't recommend it, though. "Protected" seems to me to be a watershed concept -- a good idea to float at the time, but widely open to abuse, and not very useful. A fill-in for a semantic wart, in other words.
Same goes for "friend," to be honest, which I've mostly used either to get around the limitations of the compiler (bad), or my own ignorance (worse), or to allow the test-harness a degree of "introspection" (good, but rather nasty.)
Admin
Well, it does...from the compiler. Personally, I prefer that my compiler know as many of the implementation details of my programs as it can use.
They apparently also had no idea that people who are familiar with x86 assembly can probably read the above function in hex, without bothering to disassemble it first.
Admin
It's illegal, although not all laws are equally enforced.
A lot of code breaks instantly if you prevent people from #defining keywords. Consider code that is meant to be portable between compilers that do and do not support the void, const, and inline keywords (although technically those compilers are only #defining keywords on compilers where the words in question aren't keywords...).
Note that it's also not legal to do things like redefine the class yourself with whatever access controls you like; however, C++ is not required to fail in that case (for one thing there isn't necessarily enough information available to the compiler and linker to know that this has occurred) and undefined results are correct some of the time (in the same way that a stopped clock is right every now and then).
Admin
Yes, for bug fixes. It is possible to rewrite existing methods and add new ones in most cases. There are some caveats of course--no inlining can be possible, and if you change the size or layout of the class then you have some problems to solve.
If I can force everyone who uses my class to rebuild from source every time I change the class then I can completely swap one implementation for another without rebuilding a thing. I often do this with other people's classes: when I have a whole lot of code that works, but a library that doesn't, I replace the library without rewriting my own code.
It's much easier to extend a class that uses the pImpl idiom (or Proxy/Factory design patterns). In this case the user sees class A, which has only methods and a pointer to class B. The user never sees a definition or declaration of class B, so I'm free to change it at will. Since A and B are part of the same library, any change to B that requires a change to A will necessarily be made at the same time from the user's point of view.
There are some restrictions on A but it's possible to live within them. The set of data members in A must not change (check: it's just a pointer to B, where all the good stuff happens). The set of virtual methods can be extended but only at the end of the existing list, and existing methods cannot be changed (otherwise I change the mapping of vtbl slots to methods and previously compiled binaries blow up). I can't accidentally leak information about B through inline members of A (check: that combination of code won't compile).
Terms like "private" and "public" are meaningless when applied to class B--the only way the user gets to access any member of B at all is by reinterpret-casting to void*, or by guessing the structure of B and declaring a matching class herself. Note that with default ELF linking options, a user can actually do that accidentally and it produces really obscure bugs.
[code] libfoo/ include/ // shipped to user a.h src/ // compiled into libfoo.a a.cc // libfoo.a is shipped to user b.h b.cc
userapp/ // this is the user's code user.cc
#user.cc #include "a.h"
#a.cc #include "a.h" #include "b.h"
Admin
That's why you also
#define class struct
Admin
That just means that you have a binary compatibility nightmare in C instead of a binary compatibility nightmare in assembly language.
Imagine a monkey is following you as you code, adding spurious references to members of your structs that you can't see, and ensuring that they're used almost at random throughout your code. That's what binary compatibility in C++ is like.
If you destroy a C++ object of a class that has a destructor, some function with a magic name is called for the object's destructor. This is true whether you are compiling from C++ to assembler or C++ to C--in the C code you'll get exactly the same function call.
Admin
This is what const references are for.
With a proper compiler...actually with just about any compiler...this gets optimized to exactly the same code you would have if you had directly accessed the member, except the compiler also prevents naive users from modifying the data.
Admin
I assume that facility does not work across DLL boundaries by default (or at all)?
Usually it's necessary on most DLL/DSO systems to specify explicitly what is visible, what is global, what isn't, and what can and can't be inlined...otherwise you have an ABI compatibility nightmare.
Admin
Seriously, though. If your tender sensibilities are outraged by the concept of an inline escaping from a cpp file, then :
(a) Use the usual horrible manifest constants to guard against inclusion of a cpp file (well, you wouldn't want that to happen, would you?) (b) Design the bleeding thing right in the first place.
There. Problem solved.
And, as a side-note, that's not "just-in-time" allocation (whatever that might mean) -- that's the genuinely scary Singleton Pattern.
In C++, please replace 99% of cases of this with a namespace. You'll feel better.
I believe that "Link Time Code Generation" is functionally equivalent to "template instantiation," which various other C++ compilers/linkers have had since around 1994. Nice to see Microsoft catching up. I might be mistaken, though.
O Lord, one more thing. RAII. At least use a fucking auto_ptr.
Admin
Actually the ISO text in context does just apply to standard library headers. It (and the other subsections of that chapter) makes explicit that you shall not mess with tokens in the standard library, either by #defining them, or by declaring them yourself, or by using reserved names like "__foo".
Note that these sections don't actually forbid anything, which is a good thing since it would be impossible to actually build the standard library on a compiler that forbids standard library code.
The restriction makes precompilation of standard headers easier, and relieves the implementation from the requirement to do all the usual precompilation consistency checks on the standard headers.
Users are free to #define tokens used in their own headers as much as they like. I've seen it used in the field occasionally, as a solution for dealing with really awful old compilers.
Admin
That only works for protected and public variables. Private variables are inaccessible outside of the class that declared them and its friends.
Of course, your compiler might have a template bug. ;-)
Admin
Also, every C++ programmer has either read the John Lakos book "Large-Scale C++ Software Design" and thus knows about all these issues and the large variety of solutions, or they're idiots.
But to be fair, as this site proves frequently, it doesn't matter what language you use - there are many people out there who actually are stupid, and go to great lengths to expose private implementation details while thinking they're being smart.
Admin
C# does this:
-Me
Admin
Most of the features of C++ that are "expensive" give you something in return. (Let's ignore exceptions here. They do, but it's not efficiency.)
Used purely for purposes of efficiency, vtbls are nothing more or less than a jump table to avoid arbitrarily complex switch statements in linear time.
The canonical example (Scott Meyers, passim) is the comparison between the STL sort using functors and qsort using function pointers. The former is far cheaper, for what it's worth.
However: correct first and efficient second, which is what you're really saying. And you're absolutely efficient^H^H^H^H^H^H^H^H^H correct to point that out.
BTW, if anybody is cretinous enough to use the pre-processor to redefine what public, protected, private, or even OOH_YOURE_SO_HUGE might mean, they don't need to lie again. Just use the pre-processor, in the same way that you (ahem) abused it in the first place:
#undef OOH_YOURE_SO_HUGE
That, after all, is what a pre-processor is for.
If anything.
Admin
I agree - I hate getters/setters with a passion, they had a use (GUI builders - read back in the history) and people just ran riot with them pointlessly.
Interfaces, with methods that do genuine things are the right way. Getters and Setters that expose atomic, internal data of an object break encapsulation just as much as just declaring those variables public.
Admin
Admin
Ever heard of LTCG (Link Time Code Generation AKA Whole Program Optimization)? Check Visual C 7.
Admin
For example, MS C compiler has acces qualifier as a part of member function's full name. If you change it in one module, it won't link against the member function body.
Admin
No, it's illegal in at least three different ways. Can't believe all the people who learned to program off a crackerjack box who think it is legal.
Firstly, it's illegal to #define a keyword. [C++98 lib.macro.names#2]
Secondly, it's illegal to re-#define a macro that was already defined (unless it's a function-like macro and you're defining another version with a different number of parameters). [C++98 cpp.replace#2]
Thirdly, if there is another file in the project that includes the header without molestation, then you have violated the One Definition Rule -- classes (and most other things), if declared multiple times, the declarations must be identical. [C++98 basic.def.odr#5]
The second one requires a compiler diagnostic; the others don't. (they could just fail randomly at runtime).
In C, the second point still applies, although the third is obviously moot.
Admin
Admin
Admin
Languages make a lot less difference to speed than the people designing and writing the code.
I am pretty certain I could hack up a program in an interpreted script language that works faster than some of my friend's C/C++ code, even with the compiler optimizing as much as possible.
Admin
While safety-critical code is probably not a good place for it, I don't think you can say that making variables public like this is always a bad thing.
Encapsulation is great, but it doesn't apply all the time. Sometimes a particular class will either never change implementation, or more likely, will require changing the interface anyway if the implementation changes.
For instance, an angle class. It's got a single angle variable, which could be safely read. Changing the type of the variable would change all the accessor functions anyway, so no encapsulation there. Changing from degrees to radians would mess up any code using the vector, and is pointless if just done internally - so again, no encapsulation. And honestly, what are you going to start doing that'll require encapsulating the implemenation? Caching popular angles? Storing the angles in an online database? So there is really no encapsulation to be had.
And as for "enforcing" correct use. If the variable is clearly documented as read only, then the only way people could incorrectly use it is intentionally. As seen above, you can already do that with the preprocessor.
I don't think "don't use the variable in a way explicitly forbidden by the documentation and comments" is an unreasonable request - I thought we were dealing with trained programmers here, not children on a theme-park ride.
Admin
A cpp file is processed by the compiler, a hpp file is included in cpp files by the preprocessor. HPP files are essentially a hack designed to bypass the fact that old compiler/linker systems couldn't inline functions that weren't defined in the same post-preprocessor files as they were called in. I never said inlining functions defined in cpp files was a bad idea, just that in many circumstances it's not posible.
Just-In-Time allocation is a term I made up, which means that the system allocates memory when it needs it rather than during an initialization phase. The code example is not an example of the singleton model, this is the singleton model:
class MySingleton { private: // Private constructor blocks new instances being made MySingleton(){}
public: // Singleton accessor static MySingleton &GetInstance() {return ms_Instance;} };
I guess you could mess around with name-spaces to achieve the same result, though I don't see how that would give you any particular advantage.
Finally, you have no idea what link time code generation is.
http://msdn.microsoft.com/msdnmag/issues/02/05/Hood/
Admin
Apparently so. Try to remember that we've heard this stuff said with a straight face by... well, the guy who wrote this code for example. Or a friend at university. Sarcastic voice tone doesn't come across so well IN TEXT.
Admin
Yes, but then the interface will just refuse to compile. ("class Fizzywig does not implement interface Fizzy") Change a private variable and it'll "work" just fine. Till everything explodes.
Admin
Still dangerous, as he can const_cast the const away... Don't feed the hackers ;)
CAPTCHA: burned, OUCH!
Admin
I'd be keen to see your proof (if indeed you mean proof of the mathematical kind).
The first I know of was posted only last month:
http://www.edmundkirwan.com/encap/intro.html
Admin