5

I have just read the following definition in C++ Primer (5th edition) on page 298:

A class is an aggregate if:

  • All of its data members are public

  • It does not define any constructors

  • It has no in-class initializers

  • It has no base classes or virtual functions

A definition is also provided in this post: What are Aggregates and PODs and how/why are they special?.

After all I read in the previous sections of the book on the value of encapsulation, I am wondering: why would anyone want to use an aggregate class? (BTW, the question seems to be applicable to struct in general: why would I want to have public: by default?)

Community
  • 1
  • 1
AlwaysLearning
  • 7,257
  • 4
  • 33
  • 68
  • 1
    Why not? In other words, what's your effort to answer the question? – Ulrich Eckhardt Jul 05 '15 at 16:16
  • Why not? Encapsulation! Item 22 of **Effective C++** (3rd edition) is titled: "Declare data members private"! – AlwaysLearning Jul 05 '15 at 16:20
  • 1
    @Meir Goldenberg An aggregate in turn can be a private data member of some class.:) – Vlad from Moscow Jul 05 '15 at 16:22
  • 2
    So, why encapsulation, I could ask? C++ is a multi-paradigm language that can be used for more than just object-based programming. Also, programming implies choice. An informed programmer can decide which technique is applicable and which isn't. BTW: The advise to declare data members private is just that, an advise. It's not an absolute must. – Ulrich Eckhardt Jul 05 '15 at 16:23
  • 1
    `struct` must have default visibility `public` for compatibility with C. And often times it is very useful, especially with template meta-programming where we use `static` members as a way to “return” stuff. If you don't like it, simply use `class` instead of `struct`. – 5gon12eder Jul 05 '15 at 16:31
  • 1
    The premise of this question appears to be "everything should be 'encapsulated' even though I don't understand what encapsulation means and have sucked up every lie and myth about OOP that my University professors threw at me ... and even though I haven't found out yet that C++ is not an OO language". No offence. – Lightness Races in Orbit Jul 05 '15 at 18:29

2 Answers2

10

An aggregate is basically a simple collection of data that does not have any invariants the class would have to guarantee. Since there is no invariant and thus all combinations of possible values of the member make sense, there is no point in making them private since there is nothing to protect.

A simple example for such a class would be something like

struct Point3d {
   std::array<double, 3> coordinates;
};

Since every triple of doubles is a point in R^3, there is nothing to gain by hiding the data. (If you are afraid of NaN and infinity values, this might not be the best idea. If this can happen, you might want to not make this an aggregate.)

Another example of an aggregate type is std::array. Again, it is just an array of some type and some (immutable) length, so no invariant is to protect.

One advantage of aggregates is aggregate initialization.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • I think that the `aggregate class` in C++ seems to be the same as `struct` in C. Am I right? – zhenguoli Jul 28 '17 at 01:54
  • @zhenguoli Not quite. While every C-struct is an aggregate, the converse does not hold. Aggregates may have base classes and member functions with some restrictions, for a complete list see the link at the end of my answer. – Baum mit Augen Jul 28 '17 at 09:52
  • Thank you very much. I get it. – zhenguoli Jul 28 '17 at 10:28
6

Aggregate classes can be aggregate initialized using an initializer list:

struct Agg {
    string a;
    int b;
}
Agg a = {"A string", 0};

They are mainly used as a tupple-like return value like so:

struct Response {
    bool success;
    string body; // Body is only set if success is true
}

Response foo() {
    if(failed) return {false, ""};
    return {true, "content"};
}

As you can see all four requirements have to be fulfilled for this to be meaningful (before c++11).

All of its data members are public

It's pretty much just a tuple of objects.

It does not define any constructors

Well, either you initialize all members (via aggregate initialization) or you default initialize all members (with the default constructor).

It has no in-class initializers

Same as above

It has no base classes or virtual functions

It's tuple-like, so base classes would destroy that and virtual functions don't make sense since you wouldn't inherit from such a class.

I hope this clears it up a bit. Remember that this is was invented before C++11 where std::tuple wouldn't exist so you would have used an aggregate class to return multiple values. Nowadays in most use cases you could use tuple aswell but it is not my favorite.


std::tuple vs aggregate classes

  • An aggregate class can define member functions
  • An aggregate class can overload operators.
  • An aggregate can define useful names for its attributes
  • etc.. to expand

Most of the time, aggregate classes are the way to go. tuple should only be used if you really want nothing else but returning a tuple of objects, and then "breaking it into its pieces". Member functions don't make sense most of the time but aggregate classes can still overload the cast operator for example.

Use tuples only when you only want to do nothing but retuning a bunch of objects together, without a need to "name" them (via member names in aggregates)

WorldSEnder
  • 4,875
  • 2
  • 28
  • 64