struct, class and access
A rectangle is described by two numbers: its width and its height. Kept in separate variables, they can be confused with another rectangle's sizes, and an area function must take both numbers. The struct keyword gathers such data into one new type:
#include <iostream>
struct Rect {
int width = 0;
int height = 0;
int area() { return width * height; }
};
int main() {
Rect r;
r.width = 3;
r.height = 4;
std::cout << r.area() << '\n'; // 12
}Fields and methods
Rect is a class: a type that keeps data together with the functions that work on it. The variables inside a class are its data members, or fields, and the functions are its member functions, or methods. Describing a class creates no objects: the variable r is an object of type Rect, and every object has its own fields. A field gets its initial value with = or braces, as in int width = 0;; parentheses do not work here.
The fields and methods of an object are reached with a dot: r.width, r.area(). A method is always called for a particular object, and inside the method the field names mean the fields of that object. In the call r.area(), the name width is r.width.
Fields with the same access are laid out in the object in the order they are declared. But sizeof(Rect) may turn out larger than the sum of the field sizes. The compiler may add unused bytes between fields and at the end, so each field gets an address convenient for the processor.
public and private
The public: and private: labels set who can use the fields and methods. Everything after public: is open to any code, and everything after private: is open only to the class's own methods. Outside code cannot corrupt a private field: only the methods change it, and they keep its value valid.
class Counter {
public:
void add() {
++count_;
}
int value() {
return count_;
}
private:
int count_ = 0;
};For an object Counter c;, outside code can call c.add() and c.value(), but the line c.count_ = 100; does not compile. A trailing underscore in the name is a common convention for private fields.
struct and class differ only in their default access. In a struct, fields and methods without a label are public; in a class, they are private. That is why struct is usually written for bundles of public data, and class when a type has private fields.
Common mistake
The type is declared with class, and the public: label is forgotten:
class Rect {
int width = 0;
int height = 0;
};
int main() {
Rect r;
r.width = 3; // ✗
}error: 'width' is a private member of 'Rect'In a class, fields without a label are private, so main cannot reach the field width. If the type is a bundle of public data, declare it with struct. If the fields need to stay private, add public methods that change them.