1

I'm new to learning C++. I'm trying to convert a Java application that I wrote to C++. What I can't understand is how to recreate the Enumeration classes from Java to C++. I would like to be able to create Enumeration objects which have a constructor and a toString() method.

Below is an example of my Java Enumeration:

public enum InteractionType {
    // Enumeration Values
        PRINTACTIONS("Print Available Actions"),
        PRINTBANKNAME("Display Bank Name"),
        PRINTBANKACTIONS("Display Bank Actions"),
        CREATEBRANCH("Create a Branch"),
        CREATECUSTOMER("Create a Customer"),
        READBRANCH("Query Bank Branches"),
        READCUSTOMER("Query Customers and/or Customer Transactions"),
        UPDATEBRANCH("Update Branch Name"),
        UPDATECUSTOMER("Update Customer Information"),
        DELETEBRANCH("Delete Branch"),
        DELETECUSTOMER("Delete Customer"),
        QUITAPP("Quit Application");
        
    // Private Variables
    private final String description;

    // Constructor
    InteractionType(String description) {
        this.description = description;
    }

    // Methods
    public String toString() {
        return description;
    }
}

I would then create a method in the main file to get a specific InteractionType from an array of values. An example of that method would be:

private static InteractionType getSelectedAction() {
    // Creates an array with all the values of the Enumeration Class
        InteractionType[] interactionTypes = InteractionType.values();
        System.out.print("Select an action: ");
        int id = scanner.nextInt();
        scanner.nextLine();
    // Returns a specific InteractionType
        return interactionTypes[id];
    }

This is the class I have attempted to write to recreate a Java Enumeration in C++:

InteractionType.h

#include <iostream>
#include <string>
using namespace std;

class InteractionType {
    public:
        static const InteractionType PRINTACTIONS(string = "Print Actions");
        static const InteractionType PRINTBANKNAME(string = "Print Bank Name");
        static const InteractionType PRINTBANKACTIONS(string = "Print Bank Actions");
        static const InteractionType CREATEBRANCH(string = "Create a Branch");
        static const InteractionType CREATECUSTOMER(string = "Create a Customer");
        static const InteractionType READBRANCH(string = "Read Branches");
        static const InteractionType READCUSTOMER(string = "Read Customers");
        static const InteractionType UPDATEBRANCH(string = "Update a Branch");
        static const InteractionType UPDATECUSTOMER(string = "Update a Customer");
        static const InteractionType DELETEBRANCH(string = "Delete a Branch");
        static const InteractionType DELETECUSTOMER(string = "Delete a Customer");
        static const InteractionType QUITAPP(string = "Quit Application");
    private:
        string description;
        InteractionType(string description);
};

InteractionType.cpp

#include "InteractionType.h"

const InteractionType InteractionType::PRINTACTIONS(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::PRINTBANKNAME(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::PRINTBANKACTIONS(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::CREATEBRANCH(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::CREATECUSTOMER(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::READBRANCH(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::READCUSTOMER(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::UPDATEBRANCH(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::UPDATECUSTOMER(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::DELETEBRANCH(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::DELETECUSTOMER(string description)
{
    return InteractionType(description);
}

const InteractionType InteractionType::QUITAPP(string description)
{
    return InteractionType(description);
}

InteractionType::InteractionType(string description) {
    this->description = description;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
TroyPilewski
  • 359
  • 8
  • 27
  • 1
    There is no equivalent in C++. You will need to hand-roll your own. There are many possible approaches one might take. See [enum to string in modern C++](https://stackoverflow.com/q/28828957/1553090) for more information. – paddy Jan 13 '23 at 03:06
  • 3
    `std::(unordered_)map` is a close-ish approximation. – NathanOliver Jan 13 '23 at 03:25
  • 3
    C++ is not Java. The task at hand is not how to write Java-Like enumeration in C++, but how to implement what the Java enumeration does, but in C++. – Sam Varshavchik Jan 13 '23 at 03:28
  • 1
    Use free functions. Java is a bit aggressive with the "everything must be a method" rule. In C++, it's very common to use free functions, even for things that operate on classes. The C++ Code Guidelines recommend only using member functions when you need access to internal state ([Source](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-member)). And for an `enum`, there *is* no internal state (all of the properties of an enum, the description in your example, are public knowledge and immutable to the whole program). – Silvio Mayolo Jan 13 '23 at 03:59

1 Answers1

2

Your translation is a bit off. Try this instead:

InteractionType.h

#ifndef InteractionTypeH
#define InteractionTypeH

#include <string>
#include <array>

class InteractionType {
    public:
        static const InteractionType PRINTACTIONS;
        static const InteractionType PRINTBANKNAME;
        static const InteractionType PRINTBANKACTIONS;
        static const InteractionType CREATEBRANCH;
        static const InteractionType CREATECUSTOMER;
        static const InteractionType READBRANCH;
        static const InteractionType READCUSTOMER;
        static const InteractionType UPDATEBRANCH;
        static const InteractionType UPDATECUSTOMER;
        static const InteractionType DELETEBRANCH;
        static const InteractionType DELETECUSTOMER;
        static const InteractionType QUITAPP;

        std::string toString() const;

        static std::array<InteractionType, 12> values();

    private:
        std::string description;
        InteractionType(std::string description);
};

#endif

InteractionType.cpp

#include "InteractionType.h"

const InteractionType InteractionType::PRINTACTIONS("Print Actions");
const InteractionType InteractionType::PRINTBANKNAME("Print Bank Name");
const InteractionType InteractionType::PRINTBANKACTIONS("Print Bank Actions");
const InteractionType InteractionType::CREATEBRANCH("Create a Branch");
const InteractionType InteractionType::CREATECUSTOMER("Create a Customer");
const InteractionType InteractionType::READBRANCH("Read Branches");
const InteractionType InteractionType::READCUSTOMER("Read Customers");
const InteractionType InteractionType::UPDATEBRANCH("Update a Branch");
const InteractionType InteractionType::UPDATECUSTOMER("Update a Customer");
const InteractionType InteractionType::DELETEBRANCH("Delete a Branch");
const InteractionType InteractionType::DELETECUSTOMER("Delete a Customer");
const InteractionType InteractionType::QUITAPP("Quit Application");

InteractionType::InteractionType(std::string description) {
    this->description = description;
}

std::string InteractionType::toString() const {
    return description;
}

std::array<InteractionType, 12> InteractionType::values() {
    return {
        PRINTACTIONS,
        PRINTBANKNAME,
        PRINTBANKACTIONS,
        CREATEBRANCH,
        CREATECUSTOMER,
        READBRANCH,
        READCUSTOMER,
        UPDATEBRANCH,
        UPDATECUSTOMER,
        DELETEBRANCH,
        DELETECUSTOMER,
        QUITAPP
    };
}

And then you can use it like this:

#include <iostream>
#include <limits>
#include "InteractionType.h"

void displayActions() {
    std::cout << "Actions: " << std::endl;
    size_t id = 0;
    for(auto &elem : InteractionType::values()) {
        std::cout << id++ << ':' << elem.toString() << std::endl;
    }
}

InteractionType getSelectedAction() {
    auto interactionTypes = InteractionType::values();
    std::cout << "Select an action: ";
    int id;
    std::cin >> id;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    return interactionTypes.at(id);
}

Online Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • This works great and I think that I understand most of what is happening. There are a few keywords that I don't understand. Although, since this is a class and not an enum or integer value; I cannot utilize this with a switch statement. Is there a way that I could retrieve the variable name for a single InteractionType and make a switch statement do action based on the InteractionType selected? – TroyPilewski Jan 15 '23 at 00:14
  • Adding a unique int/enum value to each class instance is trivial, just do similarly as the `description` field. And you can retrieve that value for use in a `switch` statement, eg: `InteractionType action = getSelectedAction(); switch (action.value()) {...}`. The problem is, you can’t use the values in `case` statements, eg: `case InteractionType::PRINTACTIONS.value():` won't work. – Remy Lebeau Jan 15 '23 at 01:18
  • That's exactly what I was trying to do. In my Java code I have a `switch (action) { ... }` which has a case for each action. It seems efficient than writing the same code in `if (action) { ... } elseif { ... } else { ... }`. Would you be able to show me how I would modify the code to get it's value name out? – TroyPilewski Jan 15 '23 at 02:43