Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
breakoutModewide
languagecpp
#include <stdio.h>
#include <climits>
#include <vector>
#include <string>
#include <string.h>
#include <memory>

class Attribute
{
public:
    Attribute(const char *n);
    char * toString() const; // const after the arguments means that this function does not modify anything internal to Attribute
    virtual ~Attribute(); // a virtual destructor must be defined so the derrived classes' destructors are called.

    char * name; // every attribute has a name, we should define it once here.
protected:
    virtual char * toString_impl() const = 0; // the = 0 at the end makes this a pure-virtual function.
                                              // Pure-virtual functions must be overrided by derrived classes.
                                              // Having a pure-virtual function makes this class an Abstract Class
};

Attribute::Attribute(const char *n)
{
    name = strdup(n);
    printf("Creating attribute with name %s\n", name);
}

Attribute::~Attribute()
{
    free(name);
}

// Returns an allocated string, must be freed by caller
// This is a "wrapper" to all the attribute's toString_impl().
char *
Attribute::toString() const
{
    printf("Calling toString on %s\n", name);
    return toString_impl();
}


class StringAttr : public Attribute {
public:
    StringAttr(const char *n, const char *s);
    ~StringAttr();
protected:
    char * toString_impl() const override; // override tells us that this function overrides the base class

private:
    char * value;
};

StringAttr::StringAttr(const char *n, const char *s) : Attribute(n) // Call Attribute's (const char *) constructor
{
    printf("Creating String Attr\n");
    value = strdup(s); // Since we're already calling Attributes constructor, we just need to fill in the value
}

StringAttr::~StringAttr()
{
    free(value);
}

char *
StringAttr::toString_impl() const
{
    char s[100];
    snprintf(s, sizeof(s), "%s %s", name, value);
    return strdup(s);
}

class IntegerAttr : public Attribute {
public:
    IntegerAttr(const char *n, const char *s);
    IntegerAttr(const char *n, int val);
protected:
    char * toString_impl() const override;

private:
    int value;
};

IntegerAttr::IntegerAttr(const char *n, const char *s) : Attribute(n)
{
    printf("Creating Integer Attr\n");
    value = strtol(s, nullptr, 10);
}

IntegerAttr::IntegerAttr(const char *n, int val) : Attribute(n)
{
    printf("Creating Integer Attr\n");
    value = val;
}

char *
IntegerAttr::toString_impl() const
{
    char s[100];
    snprintf(s, sizeof(s), "%s %d", name, value);
    return strdup(s);
}

int
main()
{
    std::vector<Attribute *> attrs;
    attrs.push_back(new StringAttr("jobid", "3.abcd")); // We can "upcast" StringAttr to the Attribute base class.
    attrs.push_back(new IntegerAttr("stime", "1600001031"));
    attrs.push_back(new StringAttr("select", "1:ncpus=1"));
    attrs.push_back(new IntegerAttr("qtime", 1600003201));
    // attrs.push_back(new Attribute("badattr")); // This fails because Attribute is an abstract class and cannot be instantiated

    for (const auto &attr : attrs) {
        char * out = attr->toString();
        if (auto p = dynamic_cast<StringAttr *>(attr)) { // We can "downcast" Attributes to their derived class.
            printf("String Attribute! [%s]\n", out);
        }
        else if (auto p = dynamic_cast<IntegerAttr *>(attr)) {
            printf("Integer Attribute! [%s]\n", out);
        }
        else {
            printf("%s\n", out);
        }
        free(out);
    }
    for (auto &attr : attrs) {
        delete(attr);
    }
}

...