• (cs) in reply to MoronBoy
    MoronBoy:

    public Butt getButt() { if (butt == null) { butt = new Butt(shit); } return butt; }

    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.

  • bg (unregistered) in reply to Spectre
    Spectre:
    AdT:
    mikecd:
    It's perfectly legal

    Except it's not. 17.4.3.1.1/2 of the C++ standard WD reads:

    "A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords."

    Well, since it's in the standard library chapter, it looks like it only applies to standard headers. That way, if your file does not include any standard headers, you can redefine protected, no? (Evil, evil, new realms of evil... ;-))

    No, idiot, it applies to the language. (Stupid, stupid, new realms of stupid... ;))
  • mh (unregistered)

    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:

    #define my_protected protected
    #define protected public
    
    #include <blah.h>
    
    #define protected my_protected

    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.

  • c (unregistered) in reply to mh

    #undef protected

  • (cs) in reply to Roger
    Roger:
    explaining "private/protected functions" with "information security" modell is stupid.

    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.

  • Patrick (unregistered) in reply to T.T.
    T.T.:
    Patrick:
    Let's assume for a second that this is C++ and this class defines absolutely no inline functions at all. Then a function like this:
    int the_class::get_some_int() const
    {
        return this->some_int;
    }
    

    actually ends up being a push on the stack, which can add up to lots of overhead just accessing a single integer. In Java or C# the runtime usually sees those trivial calls and inlines them, but when that code is separated into a .cpp file it's compiled and executed as a normal function, thus leading to lots of indirection. I worked at a place once which strictly forbade using inline functions (those functions defined in the header) and the performance noticeably suffered because of it. The real WTF was why the management, who understood nothing about programming, forced this upon us. They claimed that it safely hid the implementation details. They had no idea that the .h files weren't shipped with the final build of the software.

    Java has no problems with aggressive inlining, even if the code is inside another JAR. It has to do with JIT compiling, and runtime optimization (in this case runtime inlining). I'm no expert on compilers, but I think I know that much.

    The same could be done for .NET, but I don't know about .NET runtime optimization in the current .NET runtime environment.

    C++ is another beast. I'd guess it's not really possible in raw C++, unless you start using template libraries which allows aggressive optimization (inlining, processor spanning,...) but only at compile time.

    CAPTCHA: stinky, that was a funny one :)

    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.

  • (cs) in reply to MoronBoy
    MoronBoy:
    private Butt butt;

    public Butt getButt() { if (butt == null) { butt = new Butt(shit); } return butt; }

    public class HotMama{

    private Butt _back;
    
    public Butt gotBack() {
        if (_back == null) {
            _back = new Butt();
            _back.Big = true;
            _back.Round = true;
        }
        return _back;
    }
    

    }

    HotMama baby = new HotMama();

    // baby got back

  • Hans (unregistered) in reply to Scared
    Scared:
    Holy hell. I haven't used C/C++ in years and years, but please tell me that isn't legal!

    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 }

  • (cs) in reply to Geekwad
    Geekwad:
    Encapsulation is just convention. Some perfectly OO languages don't enforce it at all. Having used one for ten years, making the compiler act as a half-assed encapsulation police officer seems silly to me now. The programmer provided a perfectly good convention in place of the enforced convention provided by C++. Is anyone here really going to take the position that C++ is the one true way, and anything else is dumb? This ain't 1990...
    Certainly not, but C++ is hardly the only language that has the concept of class member visibility.

    The problem with unenforced conventions is that they tend to get ignored.

  • GrandmasterB (unregistered) in reply to brazzy
    brazzy:
    The problem with unenforced conventions is that they tend to get ignored.

    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.

  • David Schwartz (unregistered) in reply to Søren

    "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.

  • David Schwartz (unregistered) in reply to Patrick

    "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.

  • aaaaaaaah (unregistered) in reply to Steve
    Steve:
    Cyrus:
    the student thought for a second and asked, "What if they go in and change your code?".

    I've seen that before:

    #define protected public
    #include "some/header.h"
    #define protected protected
    

    Scary stuff..

    Oh God, I'm going to have nightmares about that. :-(
  • (cs) in reply to m
    m:
    I've always thought that private/protected/public thing was less than useful. If you have a class that is useful and well-written, chances are its implementation never changes. and any change to the class usually involves a re-write to the entire structure anyway, because seldom is the implemenation/interface as clear-cut as everyone wishes.

    Has anyone EVER actually changed the private implementation of a class, and not have to re-work all the stuff dependent on it? Or are my suspicions correct and this is something that lots of thought goes into for little-to-no long-term benefit?

    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

  • (cs) in reply to GrandmasterB
    GrandmasterB:
    brazzy:
    The problem with unenforced conventions is that they tend to get ignored.

    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.

    Within the same project, and if everyone is allowed to change every piece of code, yes. You shouldn't give undisciplined programmers those access rights then.

    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?

  • Jon (unregistered)

    All this talk about #define private public, and no-one mentioned the legal way to access a class's private variables in C++?

    #include "someclass.h"
    struct evil_t {} evil;
    template <>
    int SomeClass::some_template_function<evil_t>(const evil_t& muhaha) { return this->some_private_int; }

  • (cs) in reply to Scared
    Scared:
    I've seen that before:

    #define protected public

    #include "some/header.h"

    #define protected protected

    Scary stuff..

    Holy hell. I haven't used C/C++ in years and years, but please tell me that isn't legal!

    classy.h:
    class Classy { public: Classy();
        int get_var(void);
        void set_var(int v);
    
    private:
        int var;
    

    };

    classy.cpp:
    #include "classy.h"

    Classy::Classy() { var = 5; }

    int Classy::get_var(void) { return var; }

    void Classy::set_var(int v) { var = v; }

    main.cpp:
    #include <stdio.h>

    #define private public #include "classy.h" #undef private

    int main(void) { Classy *c;

    c = new Classy();
    
    printf("get_var(): %d\n", c->get_var());
    c->var = 1337;
    printf("get_var(): %d\n", c->get_var());
    
    return 0;
    

    }

    $$ g++ -o classy classy.cpp main.cpp $$ ./classy get_var(): 5 get_var(): 1337

    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.

  • whicker (unregistered) in reply to Jon

    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?

  • Tilendor (unregistered)

    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

  • (cs) in reply to whicker
    whicker:
    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?

    In C/C++ this is impossible due to pointers.

    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.

  • iToad (unregistered) in reply to Tilendor
    Tilendor:
    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

    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.

  • (cs) in reply to fist-poster
    fist-poster:
    Now this makes me understand why some people suggest putting private stuff first (without the private keyword). So only private things are well protected.

    Though it seems to me that you can also access private members and methods through pointers. All you need to know is the type and the name.

    (1) Putting "private" stuff first is not a hell of a lot of guarantee. Works for classes, doesn't for structs. (2) It's not a security issue, it's a maintenance issue, and a scalability issue. No short-cuts, no muss, no fuss. (3) Nope, you're wrong. Trivially, the point of defining a data member as private is that you can't access it, even given the name. Somewhat less trivially, and for the same reason, you can't call a private member function unless through a member function pointer -- which is such an obstrusely silly idea that I've never even had to think about it -- and would require some sort of public member function or data member to make it accessible.

    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.)

  • Zygo (unregistered) in reply to Patrick
    Patrick:
    Let's assume for a second that this is C++ and this class defines absolutely no inline functions at all. Then a function like this:
    int the_class::get_some_int() const
    {
        return this->some_int;
    }
    

    actually ends up being a push on the stack, which can add up to lots of overhead just accessing a single integer.
    ... The real WTF was why the management, who understood nothing about programming, forced this upon us. They claimed that it safely hid the implementation details.

    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 had no idea that the .h files weren't shipped with the final build of the software.

    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.

  • Zygo (unregistered) in reply to Scared
    Scared:
    I've seen that before:

    #define protected public

    #include "some/header.h"

    #define protected protected

    Scary stuff..

    Holy hell. I haven't used C/C++ in years and years, but please tell me that isn't legal!

    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).

  • Zygo (unregistered) in reply to m
    m:
    I've always thought that private/protected/public thing was less than useful. If you have a class that is useful and well-written, chances are its implementation never changes. and any change to the class usually involves a re-write to the entire structure anyway, because seldom is the implemenation/interface as clear-cut as everyone wishes.

    Has anyone EVER actually changed the private implementation of a class, and not have to re-work all the stuff dependent on it? Or are my suspicions correct and this is something that lots of thought goes into for little-to-no long-term benefit?

    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"

  • Zygo (unregistered) in reply to mikecd
    mikecd:
    Scared:
    Holy hell. I haven't used C/C++ in years and years, but please tell me that isn't legal!
    It's perfectly legal (why wouldn't it be?) but it won't always work... "class" declarations start with an implicit "private" that wouldn't be changed unless explicitly declared.

    That's why you also

    #define class struct

  • Zygo (unregistered) in reply to T.T.
    T.T.:
    dkf:
    Patrick:
    I worked at a place once which strictly forbade using inline functions (those functions defined in the header) and the performance noticeably suffered because of it. The real WTF was why the management, who understood nothing about programming, forced this upon us. They claimed that it safely hid the implementation details. They had no idea that the .h files weren't shipped with the final build of the software.
    That's actually not a WTF. The point is that it makes it possible (with some clever coding admittedly) to evolve the implementation of the interface without changing the ABI of the library. If you're inlining stuff in the interfaces, that goes out of the window. (Note, it's much much easier to do this with C code than with C++ code.)

    Note that some C++ compilers translate to C before compiling (Comeau C++ does that IIRC).

    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.

  • Zygo (unregistered) in reply to Søren
    Søren:
    So, um. I don't get what's so bad about this.

    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.

    This is what const references are for.

    inline const Foo& getFoo() { return my_foo; }

    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.

  • Zygo (unregistered) in reply to Devi
    Devi:
    MoronBoy:

    public Butt getButt() { if (butt == null) { butt = new Butt(shit); } return butt; }

    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.

    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.

  • (cs) in reply to Devi
    Devi:
    MoronBoy:

    public Butt getButt() { if (butt == null) { butt = new Butt(shit); } return butt; }

    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.

    And the difference between a cpp file and an hpp file would be ... er ... what?

    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.

  • Zygo (unregistered) in reply to bg
    bg:
    Spectre:
    AdT:
    mikecd:
    It's perfectly legal

    Except it's not. 17.4.3.1.1/2 of the C++ standard WD reads:

    "A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords."

    Well, since it's in the standard library chapter, it looks like it only applies to standard headers. That way, if your file does not include any standard headers, you can redefine protected, no? (Evil, evil, new realms of evil... ;-))

    No, idiot, it applies to the language. (Stupid, stupid, new realms of stupid... ;))

    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.

  • Zygo (unregistered) in reply to Jon
    Jon:
    All this talk about #define private public, and no-one mentioned the legal way to access a class's private variables in C++?
    #include "someclass.h"
    struct evil_t {} evil;
    template <>
    int SomeClass::some_template_function<evil_t>(const evil_t& muhaha) { return this->some_private_int; }

    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. ;-)

  • Anon (unregistered) in reply to m
    m:
    Has anyone EVER actually changed the private implementation of a class, and not have to re-work all the stuff dependent on it? Or are my suspicions correct and this is something that lots of thought goes into for little-to-no long-term benefit?
    Yes, many people often fix bugs in their code without breaking every piece of code that calls the function that contains the bug. Many people also swap out internal implementations, for example replacing arrays with lists and lists with hash maps as necessary.

    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.

  • (cs) in reply to whicker
    whicker:
    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?

    C# does this:

    class foo
    {
        private string _bar;
    
        // read only property
        public string Bar
        {
            get { return _bar; }
        }
    
        private string _fooBar;
    
        // write only property 
        // (but this is not advised, use a function instead)
        public string FooBar
        {
            set { _fooBar = value; }
        }
    }
    

    -Me

  • (cs) in reply to mh
    mh:
    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:
    #define my_protected protected
    #define protected public
    
    #include <blah.h>
    
    #define protected my_protected

    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.

    Assembler, probably. C, I'm not convinced.

    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.

  • Mycroft (unregistered) in reply to m
    m:
    Has anyone EVER actually changed the private implementation of a class, and not have to re-work all the stuff dependent on it? Or are my suspicions correct and this is something that lots of thought goes into for little-to-no long-term benefit?

    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.

  • Jon (unregistered) in reply to Zygo
    Zygo:
    Jon:
    All this talk about #define private public, and no-one mentioned the legal way to access a class's private variables in C++?
    #include "someclass.h"
    struct evil_t {} evil;
    template <>
    int SomeClass::some_template_function<evil_t>(const evil_t& muhaha) { return this->some_private_int; }
    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. ;-)

    It's a specialisation of a member function in SomeClass, so of course it can access private members of SomeClass instances :). Here's a complete program so you can test it (pretend everything above the comment is included from someclass.h):
    class SomeClass
    {
    int some_private_variable;
    public:
    SomeClass() : some_private_variable(10) { }
    template <class T> int some_template_function(const T& t) { return 42; }
    };
    //--------------------------------------
    #include <iostream>
    struct evil_t {} evil;
    template <>
    int SomeClass::some_template_function<evil_t>(const evil_t& muhaha) { return this->some_private_variable; }
    int main()
    {
    SomeClass sc;
    std::cout << sc.some_template_function(evil) << std::endl;
    }

  • Alex Gergoriev (unregistered) in reply to Patrick
    Patrick:
    Let's assume for a second that this is C++ and this class defines absolutely no inline functions at all. Then a function like this:
    int the_class::get_some_int() const
    {
        return this->some_int;
    }
    

    actually ends up being a push on the stack, which can add up to lots of overhead just accessing a single integer.

    Ever heard of LTCG (Link Time Code Generation AKA Whole Program Optimization)? Check Visual C 7.

  • Alex Gergoriev (unregistered) in reply to Scared
    Scared:
    I've seen that before:

    #define protected public

    #include "some/header.h"

    #define protected protected

    Scary stuff..

    Holy hell. I haven't used C/C++ in years and years, but please tell me that isn't legal!

    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.

  • Old Wolf (unregistered) in reply to Scared
    Scared:
    #define protected public #include "some/header.h" #define protected protected

    Holy hell. I haven't used C/C++ in years and years, but please tell me that isn't legal!

    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.

  • Old Wolf (unregistered) in reply to mh
    mh:
    #define my_protected protected
    #define protected public
    #include <blah.h>
    #define protected my_protected
    Oh. My. God.
    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.
    C++ is equal or faster in performance to C.
  • Old Wolf (unregistered) in reply to brazzy
    brazzy:
    whicker:
    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
    In C/C++ this is impossible due to pointers.
    Rubbish. In fact some vendors already offer this functionality; Borland C++ 5.5 and later has it.
  • rawr (unregistered) in reply to Old Wolf
    Old Wolf:
    mh:
    #define my_protected protected
    #define protected public
    #include <blah.h>
    #define protected my_protected
    Oh. My. God.
    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.
    C++ is equal or faster in performance to C.
    That depends entirely on design, whats being done and the programmers you used to deliver the code.

    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.

  • Someone (unregistered)

    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.

  • (cs) in reply to real_aardvark
    real_aardvark:
    And the difference between a cpp file and an hpp file would be ... er ... what?

    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.

    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(){}

      // singleton instance
      static MySingleton ms_Instance;
    

    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/

  • (cs) in reply to FredSaw
    Is it so difficult to realize that Alex is speaking from the point of view of the WTF author?

    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.

  • (cs) in reply to GrandmasterB

    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.

  • T.T. (unregistered) in reply to Zygo
    Zygo:
    Søren:
    So, um. I don't get what's so bad about this.

    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.

    This is what const references are for.

    inline const Foo& getFoo() { return my_foo; }

    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.

    Still dangerous, as he can const_cast the const away... Don't feed the hackers ;)

    CAPTCHA: burned, OUCH!

  • Ed Kirwan (unregistered) in reply to Phylyp

    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

  • Synonymous Awkward (unregistered) in reply to mh
    mh:
    #define my_protected protected
    #define protected public
    

    #include <blah.h>

    #define protected my_protected

    So what you're saying is, you have never used a preprocessor macro and/or have no clear understanding of how they work.

    Someone:
    I thought we were dealing with trained programmers here, not children on a theme-park ride.
    Are you sure you're on the right website?

Leave a comment on “Safety Critical Encapsulation”

Log In or post as a guest

Replying to comment #:

« Return to Article