0

I have a class defined like this:

#include <vector>
#include <string>
#include <iostream>
#include <sstream>

using namespace std;

class Shape {
protected:
    float width, height;
public:
    virtual ~Shape(){}

    void set_data (float a, float b){
        width = a;
        height = b;
    }

    virtual string getType() {
        return "Shapes";
    }
};

class Polygon: public Shape {
public:
    virtual ~Polygon(){};

    virtual string getType() {
        return "Polygon";
    }
};

class Triangle: public Polygon {
    public:
        virtual ~Triangle(){};

    virtual string getType() {
        return "Triangle";
    }
};

And I want to get a program that uses this class

int main () {
    Shape poly = Polygon();
    Shape tri = Triangle();
    std::cout << poly.getType() << std::endl;
    std::cout << tri.getType() << std::endl;
    return 0;
}

Is there a way to get poly.getType() to print out Polygon, for example? Right now it is printing out Shapes. I know if I did

Polygon poly = Polygon()

that does the trick, but I want to store poly as a Shape object, construct it using a Polygon constructor, and ensure that

poly.getType()

returns Polygon, not Shapes.

ndb
  • 127
  • 1
  • 10

4 Answers4

2

Polymorphism only works with non-value types; i.e. with references and pointers. And since references must be immediately bound they are not much use here.

Your best bet is to use std::unique_ptr<Shape> poly(new Polygon()); and call using

poly->getType();

I'm using std::unique_ptr so I don't need to call delete explicitly. std::shared_ptr would work too but do consult the documentation so you use the one most appropriate to your use case.

By the way, you don't need to repeat virtual when overriding the function in child classes. You only need to mark the function virtual in the base class.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

Your code suffers from object slicing. Use:

int main () {
    std::unique_ptr<Shape> poly = new Polygon();
    std::unique_ptr<Shape> tri = new Triangle();
    std::cout << poly->getType() << std::endl;
    std::cout << tri->getType() << std::endl;
    return 0;
}
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thanks, this is exactly what I want. Will accept once stack overflow allows me to – ndb Nov 26 '14 at 22:24
  • Cute (+1) but if `getType()` were to throw an exception, you'll leak memory. – Bathsheba Nov 26 '14 at 22:25
  • @Bathsheba, I'm trying to get in the habit of using `std::unique_ptr` and `std::shared_ptr` whenever it's appropriate. Old habits. – R Sahu Nov 26 '14 at 22:27
0

Make a variable String type. Set it in each instantiable subclass. Have a function getType in Shape that returns it.

davidc
  • 132
  • 1
  • 4
0

That answer above was basically right: "I need to use pointers" is the key.

This solved my problem:

int main ()
{
    Polygon poly = Polygon();
    Shape* testing = &poly;
    std::cout << testing->getType() << std::endl;
    return 0;
}

I will accept your answer in about an hour's time because Stack overflow makes me wait for a while before accepting. Thanks

ndb
  • 127
  • 1
  • 10