C++ Structs with Member Functions vs. Classes with Public Variables

前端 未结 6 558
感动是毒
感动是毒 2020-12-13 09:30

This is really a question of good form/best practices. I use structs in C++ to form objects that are designed to basically hold data, rather than making a class with a ton o

相关标签:
6条回答
  • 2020-12-13 10:16

    In C++, Structs are classes, with the only difference (that I can think of, at least) being that in Structs members are public by default, but in classes they are private. This means it is perfectly acceptable to use Structs as you are - this article explains it well.

    0 讨论(0)
  • 2020-12-13 10:21

    I don't want to sparkle a holy war here; I usually differentiate it in this way:

    • For POD objects (i.e., data-only, without exposed behavior) declare the internals public and access them directly. Usage of struct keyword is convenient here and also serves as a hint of the object usage.
    • For non-POD objects declare the internals private and define public getters/setters. Usage of class keyword is more natural in these cases.
    0 讨论(0)
  • 2020-12-13 10:25

    I think there are two important design principles to consider here:

    1. Hide a class's representation through an interface if there is some invariant on that class.

      A class has an invariant when there is such thing as an invalid state for that class. The class should maintain its invariant at all times.

      Consider a Point type that represents a 2D geometric point. This should just be a struct with public x and y data members. There is no such thing as an invalid point. Every combination of x and y values is perfectly fine.

      In the case of a Person, whether it has invariants depends entirely on the problem at hand. Do you consider such things as an empty name as a valid name? Can the Person have any date of birth? For your case, I think the answer is yes and your class should keep the members public.

      See: Classes Should Enforce Invariants

    2. Non-friend non-member functions improve encapsulation.

      There's no reason your age function should be implemented as a member function. The result of age can be calculated using the public interface of Person, so it has no reason to be a member function. Place it in the same namespace as Person so that it is found by argument-dependent lookup. Functions found by ADL are part of the interface of that class; they just don't have access to private data.

      If you did make it a member function and one day introduced some private state to Person, you would have an unnecessary dependency. Suddenly age has more access to data than it needs.

      See: How Non-Member Functions Improve Encapsulation

    So here's how I would implement it:

    struct Person {
      std::string name;
      DateObject dob;
    };
    
    int age(const Person& person) {
      return calculated age from person.dob;
    }
    
    0 讨论(0)
  • 2020-12-13 10:28

    In C++, the only difference between structs and classes are that structs are publicly visibly by default. A good guideline is to use structs as plain-old-data (POD) that only hold data and use classes for when more functionality (member functions) is required.

    You may still be wondering whether to just have public variables in the class or use member functions; consider the following scenario.

    Let's say you have a class A that has a function GetSomeVariable that is merely a getter for a private variable:

    class A
    {
        double _someVariable;
    
    public:
        double GetSomeVariable() { return _someVariable; }
    };
    

    What if, twenty years down the line, the meaning of that variable changes, and you have to, let's say, multiply it by 0.5? When using a getter, it is simple; just return the variable multiplied by 0.5:

        double GetSomeVariable() { return 0.5*_someVariable; }
    

    By doing this, you allow for easy maintainability and allow for easy modification.

    0 讨论(0)
  • 2020-12-13 10:28

    "Use a struct only for passive objects that carry data; everything else is a class."

    say google guidlines, I do it this way and find it a good rule. Beside that I think you can define your own pragmatics, or deviate from this rule if it really makes sense.

    0 讨论(0)
  • 2020-12-13 10:30

    If you want some data holder then prefer struct without any get/set methods.

    If there is more to it, as in this case "Person".

    1. It models real world entity,
    2. Has definite state and behaviour,
    3. Interacts with external world,
    4. Exhibits simple/complex relationship with other entities,
    5. it may evolve overtime,

    then it is a perfect candidate for a class.

    0 讨论(0)
提交回复
热议问题