CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 23
  1. #1
    Join Date
    Nov 2014
    Posts
    37

    Opinions on my get/set approach

    I did a forum and google search on c++ getters and setters and found way too many hits and many diverse opinions.
    I would ask your opinion on the approach I present here.
    Early in my c++ studies I found I missed the built in getters and setters from my early VB days and more recently from PowerBASIC COM classes. I found a c++ template which I have used but it was lacking in it's implementation.
    Recently I ran across another approach which I suplimented with the macros: PropGet,PropSet and PropGetSet.
    Early on in my c++ education I adopted the method of prefixing all my private/protected variables with "m_"
    This provides me with setters/getters with a minimum amount of coding.

    Thank you,
    James

    Code:
    #include <iostream>
    #include <string>
    typedef signed char SCHAR;
    using namespace std;
    //==============================================================================
    #define PropGet(p,t) t p(){return m_##p;}
    #define PropSet(p,t) void p(t p){m_##p=p;}
    #define PropGetSet(p,t) PropGet(p,t)PropSet(p,t)
    //==============================================================================
    
    class PropTestOne
    {
    protected:
        int      m_Count;
        long     m_v1;
        float    m_f1;
        string   m_S1;
        SCHAR    m_c1;
    public:
        PropGetSet(Count, int);
        PropGetSet(v1, long);
        PropGetSet(f1, float);
        PropGetSet(S1, string);
        PropGetSet(c1, SCHAR);
    };
    
    class PropTestTwo
    {
    protected:
        string  m_first;
        string  m_mid;
        string  m_last;
        string  m_full;
    public:
        PropGetSet(first, string);
        PropGetSet(mid, string);
        PropGetSet(last, string);
        PropGetSet(full, string);
    };
    
    int f1 (int n1, int n2)
    {
        return n1 + n2;
    }
    
    int main ()
    {
        PropTestOne  test1;
        PropTestTwo  test2;
        int      i = {0};
        int      j = {0};
        float    f = {0.0};
        SCHAR    c = {0};
        string  xs;
        //assign the value 5 to i
        i = 5;
        //assign test1 Count variable the value of i
        test1.Count(i);
        //Print the contents of test1's Count Variable
        cout << test1.Count() << endl;
        //assign the value 8 to i
        i = 8;
        //assign test1 Count variable the value of i again
        test1.Count(i);
        //assign j the value of it's Count Variable
        j = test1.Count();
        //did it work?
        cout << "j = " << j << endl;
        //Continue......
        test1.Count(327);
        cout << "test1.Count = " << test1.Count() << endl;
        //use v1
        test1.v1(134567);
        j = test1.v1();
        cout << " j = " << j << endl;
        //assign one test1 var to another
        test1.v1(test1.Count());
        cout << "test1.v1 = " << test1.v1() << endl;
        //do a bit of addition
        j = test1.v1() + test1.Count();
        cout << "j = " << j << endl;
        //how about floats?
        test1.f1(134.567);
        f = test1.f1();
        cout << "f = " << f << endl;
        f = test1.f1() + 100.789321;
        cout << "f = " << f << endl;
        //will it work with	a c++ std library string
        test1.S1("James");
        xs = test1.S1();
        cout << " xs = " << xs << endl;
        test1.c1(-88);
        c = test1.c1();
        cout << "c = " << (float)c << endl;
        //Print "c = ";c
        test2.first("James");
        test2.mid("C.");
        test2.last("Fuller");
        xs = test2.first() + " " + test2.mid() + " " + test2.last();
        test2.full(xs);
        cout << "xs = " << xs << endl;
        j = f1( test1.v1(), test1.Count());
        cout << "pass props to function" << endl;
        cout << "j = " << j << endl;
    }

  2. #2
    Join Date
    Jul 2002
    Posts
    2,543

    Re: Opinions on my get/set approach

    Unreadable and undebuggable. Just use plain C++ code for every property. Don't forget that get functions are usually defined as const.

  3. #3
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Opinions on my get/set approach

    1) this uses macro's which is something you should try to avoid, especially in libraries since defines 'pollute' the global namespace.
    2) A second problem with macro's is that you can't visibly debug through a macro, this is somewhat irrelevant in tunctions this small as here, but it can be problematic in elaborate macros.

    A better approach would be to make a template to implement get/set behaviour (typically a getable, overloaded by a setable since it's rare that you can set something but can't get it).
    This would also have the advantage that defining the type and value automatically makes it get/setable. so you don't need a 2nd set of matching declarations to match the variables to their get/set functions.

    roughly (exercise to you)
    define a template class 'getable' with template parameter T which is your type.
    use operator() to get the value.
    define a template class 'setable' with template parameter T which derives from getable<T>
    use operator (T t) to set the value (note get will appear to stop working, can you figure out why and how to solve this ?)

    then you'll have something like:
    Code:
    class PropTest
    {
    public:
        setable<int> Count;
        setable<long> v1;
        // .. others
    };
    You will of course need a means to set/initialise a value for a getable-only. initialisation would be through the constructor, if you need post-construction private setting this'll take some work.
    this approach (nor did yours) doesn't provide set-by-reference or set-by-move it only does set-by-value this has it's drawbacks, but may be exactly what you were after. if you need the others, that'll take a bit of extra work as well.

  4. #4
    Join Date
    Jul 2013
    Posts
    576

    Re: Opinions on my get/set approach

    Quote Originally Posted by jcfuller View Post
    I did a forum and google search on c++ getters and setters and found way too many hits and many diverse opinions.
    If getters and setters can be generated automatically for a variable then you don't need them. Then you can as well expose and access the variable directly.

    To routinely, manually or automatically, add getters/setters for all variables of a class is bad. It doesn't increase encapsulation and it effectively reduces the class to a mere record for shuffling data in and out.

    Have a look here at the seminal "evil" article by Holub,

    http://www.javaworld.com/article/207...-are-evil.html

    It started an intense discussion in the Java community which settled with the general consensus that routinely spraying classes with getters/setters is evil indeed, and that applies to C++ as well.
    Last edited by razzle; January 11th, 2015 at 07:01 AM.

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Opinions on my get/set approach

    The purpose of getters and setters is to be able to provide users of a class with a mechanism of obtaining or setting data held within the class without knowing anything about the underlying data structures used in the class. So that if the way that a class stores data is changed, users of the class don't have to change how they use the class. Also a setter should validate any input provided before it updates any data held by the class. A classic case of data changing is whether a class stores a date as day/month/year or as number of seconds since a known date. Whichever class internal represenation is used, the user of the class could still use class functions SetDate() and GetDate() (with overrides as required).
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Opinions on my get/set approach

    Another reason for using setters/getters is encapsulation of locks used in thread synchronization.

    If thread safety is important, then exposing a public class field requires that users of the field synchronize properly. If a getter/setter is used, the synchronization can be internal to the class and hidden from the callee.

  7. #7
    Join Date
    Jul 2013
    Posts
    576

    Re: Opinions on my get/set approach

    Quote Originally Posted by Arjay View Post
    Another reason for using setters/getters is encapsulation of locks used in thread synchronization.
    I know it's not always possibe but the preferred alternative is to make classes immutable. If means the internal state of a class is frozen upon object construction and never changes after that. There simply are no setters since objects never change. An immutable object will be thread-safe.

  8. #8
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Opinions on my get/set approach

    Quote Originally Posted by Arjay View Post
    Another reason for using setters/getters is encapsulation of locks used in thread synchronization.

    If thread safety is important, then exposing a public class field requires that users of the field synchronize properly. If a getter/setter is used, the synchronization can be internal to the class and hidden from the callee.
    while you certainly CAN do synchronisation like this, it's not usually a good idea to do this on individual member get/set's.
    sets and gets typically happen in groups, and you want to synchronise the setting/getting of the group. For performance reasons at least, and possibly for internal consistency.

  9. #9
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Opinions on my get/set approach

    Quote Originally Posted by razzle View Post
    I know it's not always possibe but the preferred alternative is to make classes immutable. If means the internal state of a class is frozen upon object construction and never changes after that. There simply are no setters since objects never change. An immutable object will be thread-safe.
    if by "immutable object" you mean static const-ness... 'sort of' otherwise: 'not really'

    immutability in C++ can be overriden.

  10. #10
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Opinions on my get/set approach

    I think razzle is referring to a class where the member variables are private (and not declared mutable), and all the non-static member functions are const member functions. This way, even if objects of the class are not declared const, they are still immutable in the sense that there does not exist any way by which the state of the object can be changed after the object has been created.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  11. #11
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Opinions on my get/set approach

    Quote Originally Posted by laserlight View Post
    I think razzle is referring to a class where the member variables are private (and not declared mutable), and all the non-static member functions are const member functions
    ... including compiler generated ones ( eg. may need a deleted move constructor/assignment operator ); moreover, in general, construction sideffects may still need synchronization ... maybe ruzzle's referring to the functional programming idea of immutability that in turn implies synchronization.

    Quote Originally Posted by OReubens View Post
    immutability in C++ can be overriden.
    not since c++11, we have constexpr to write "truly" immutable objects ( in the sense that those objects exists at compile time only ), with the caveat that it's not so easy to see naked-eye when a constexpr is actually executed at compile time or not....

    Quote Originally Posted by OReubens View Post
    while you certainly CAN do synchronisation like this, it's not usually a good idea to do this on individual member get/set's.
    sets and gets typically happen in groups, and you want to synchronise the setting/getting of the group. For performance reasons at least, and possibly for internal consistency.
    ... and for external (=user pov) consistency too: if the user of a class wants to atomically access a property he/she will probably wants to atomically access any combination of those properties as well, rendering those "automatically" thread safe properties quite useless in nontrivial scenarios ( like a thread-safe std::cout, and it's ability of "safely" writing garbage to standard output when invoked my multiple threads ... ).

    yes, I'm not a fan of "properties" in general ...

  12. #12
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Opinions on my get/set approach

    Quote Originally Posted by OReubens View Post
    while you certainly CAN do synchronisation like this, it's not usually a good idea to do this on individual member get/set's.
    sets and gets typically happen in groups, and you want to synchronise the setting/getting of the group. For performance reasons at least, and possibly for internal consistency.
    Maybe - it depends on the granularity you need. However, the point isn't about the granularity, it's about encapsulating the synchronization.

  13. #13
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Opinions on my get/set approach

    Quote Originally Posted by Arjay View Post
    Maybe - it depends on the granularity you need. However, the point isn't about the granularity, it's about encapsulating the synchronization.
    exactly, and the question is, are locking properties the right way of encapsulating synchronization ? ( note that you mentioned locking as a *reason* for using getters/setters ) I don't think so. Such an approach focuses on a narrow view of thread "safety" meant just as "it does not crash with threads". Thread safety means more than that ...
    of course, I'm not against protecting methods with locks per se ( eventually offering multiple levels of granularity ), but getters/setters often are just public fields ( badly ) disguised, politically correct POD struct fields ...

  14. #14
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Opinions on my get/set approach

    Superbonzo got what I meant.

    Not synchronizing is an Obvious flaw and your code crashes or produces 'funny' results.

    But the code not crashing nor returning funny results doesn't mean your synchronisation is well done either.

    I've seen plenty of code that ran perfectly within spec, but where they complained about "it runs slower than the single threaded solution" simply because of synchronising way too much.

    -

    The big misunderstanding many programmers have is that multitasking is NOT about making code run faster. In fact, it is guaranteed to Always run slower (because you're adding code and that code may block).
    It's about "more overall throughput" and in the case of GUI's about responsiveness.

    It's the same kind of confusion developers (and even network specialists) have about latency (single thread speed) and bandwidth (multithreaded throughput). I still have bad memories of that one time where I was trying to explain to the "network guru" of a company why the software they had running on a server in the US was never goign to get the results they wanted on the server in Europe because of latency (lightspeed is limited, who would have known), and that "that bigger bandwidth upgrade" wasn't going to change that at all.

  15. #15
    Join Date
    Jul 2013
    Posts
    576

    Re: Opinions on my get/set approach

    Quote Originally Posted by OReubens View Post
    if by "immutable object" you mean static const-ness... 'sort of' otherwise: 'not really'

    immutability in C++ can be overriden.
    I mean immutability in the general design sense.

    The definition is simple: A class is immutable if objects cannot be changed after instantiation (regardless of how this is accomplished and enforced in a given language).

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured