...
Code Block | ||||
---|---|---|---|---|
| ||||
#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);
}
} |
...