C++ Tutorial
C++ Enums
enum names a set of integer constants so you write Color::Red instead of a magic number.
Names instead of magic numbers
A traffic light is not “0, 1, or 2” in your head. It is red, amber, or green. If you storeint light = 1;, every reader has to remember what 1 means. An enum gives those integers names the compiler understands.
This tutorial uses enum class. The values live inside the type:Color::Red, not a loose Red that collides with other names.
Write an enum class
List the names in braces. The compiler assigns integers starting at zero unless you set them yourself. You almost never need the integers. You need the names.
Example
#include <iostream>
using namespace std;
enum class Color { Red, Amber, Green };
int main() {
Color light = Color::Green;
if (light == Color::Green) {
cout << "go" << endl;
}
light = Color::Red;
if (light == Color::Red) {
cout << "stop" << endl;
}
return 0;
}Compare with ==. Assign with =. You cannot assign a plain int to aColor by accident: light = 2; is an error. That is the point of enum class.
switch on an enum
A switch is a good fit when every value of the enum should take a different path. Write acase for each enumerator. Put break; at the end of each case so execution does not fall through.
Example
#include <iostream>
using namespace std;
enum class Color { Red, Amber, Green };
int main() {
Color light = Color::Amber;
switch (light) {
case Color::Red:
cout << "halt" << endl;
break;
case Color::Amber:
cout << "wait" << endl;
break;
case Color::Green:
cout << "proceed" << endl;
break;
}
return 0;
}If you later add Color::Blue, the switch will not mention it. Many compilers warn about that. Handle the new case, or you silently do nothing for a value you forgot.
Why enum class, not plain enum
Older C++ has unscoped enum Color { Red, Green };. Those names leak into the surrounding scope. Two enums cannot both have a Red. An int can mix with the enumerators without a cast.
| enum class | plain enum | |
|---|---|---|
| Write a value | Color::Red | Red |
| Names stay scoped | Yes | No |
| Mix with int | No, unless you cast | Yes, too easily |
Prefer enum class in new code. This course will not use the unscoped form.
The integers are still there
Under the hood, Color::Red is 0, Amber is 1,Green is 2. You can set your own numbers if a file format or a protocol requires them:enum class Status { Ok = 200, NotFound = 404 };.
Example
#include <iostream>
using namespace std;
enum class Status { Ok = 200, NotFound = 404 };
int main() {
Status code = Status::NotFound;
if (code == Status::Ok) {
cout << "ready" << endl;
} else {
cout << "missing" << endl;
}
cout << "stored as " << static_cast<int>(code) << endl;
return 0;
}static_cast<int>(code) is the honest way to print the number. Do not treat the enum as anint in everyday logic. Compare to other enumerators. Switch on the type. Leave the integers for storage and debugging.
Where enums fit
Use an enum for a closed set of choices: a color, a status, a difficulty, a day of the week. Do not use it for values that grow without a fixed list, such as a player’s score. That is still an int.
You cannot cout << light directly for an enum class. Print a string in each case of a switch, or cast to int when you truly want the number.
Next: a reference is another name for a variable you already have.
Worked examples
The short listings above are there so you can see the grammar. The programs here use the same statements on quantities that already have units: a speed, a pH, a count of bases. They are classroom numbers. Air resistance is ignored. g is 9.81 m/s² unless a line says otherwise.
Open them in the C++ editor at /cpp/try. Change one measurement and check whether the result still has the right unit.
Chemistry
Named phases
Solid, liquid, gas are not 0, 1, 2 in nature. They are names. enum class lets the program use Phase::Gas while the machine still stores a small integer.
if (water == Phase::Gas) reads like the sentence in the textbook. if (water == 2) does not.
Example
#include <iostream>
using namespace std;
enum class Phase { Solid, Liquid, Gas };
int main() {
Phase water = Phase::Gas;
cout << "code = " << static_cast<int>(water) << endl;
if (water == Phase::Gas) {
cout << "steam" << endl;
}
return 0;
}Physics
Open or closed circuit
A switch is a two-state device. Current needs a closed loop. Open and Closed as enum values stop you mixing 0/1 with some other flag in the same file.
Example
#include <iostream>
using namespace std;
enum class Circuit { Open, Closed };
int main() {
Circuit lamp = Circuit::Closed;
cout << (lamp == Circuit::Closed ? "current can flow" : "open circuit") << endl;
return 0;
}