Thomas Chen
Thomas Chen

Reputation: 27

In C++, can I have an interface variable just like in Java?

In Java, we can declare an interface variable without instantiation. This can help us deal with some abstract concepts. In the following Java example, I defined an interface UShape and two UShape classes, Rectangle and Triangle. In the test class bucket, I am able to define a private interface variable called myshape and do things with this variable.

interface UShape {
    void setwidth(int i);
    void setheight(int i);
    int getarea();
}

class Rectangle implements UShape{
    private int w, h;

    @Override
    public void setwidth(int i) {
        this.w = i;
    }

    @Override
    public void setheight(int i) {
        this.h = i;
    }

    @Override
    public int getarea() {
        return this.w * this.h;
    }
}

class Triangle implements UShape{
    private int w, h;

    @Override
    public void setwidth(int i) {
        this.w = i;
    }

    @Override
    public void setheight(int i) {
        this.h = i;
    }

    @Override
    public int getarea() {
        return this.w * this.h / 2;
    }
}

class bucket{
    private UShape myshape;

    //do something with myshape
    public void defineShape(int i){
        if (i == 1){
            myshape = new Rectangle();
            myshape.setwidth(5);
            myshape.setheight(5);
        }
    }

    public void printArea(){
        System.out.println(myshape.getarea());
    }

}


public class TestShape {
    public static void main(String[] args){
        bucket b = new bucket();
        b.defineShape(1);
        b.printArea();
    }
}

My question now is, in C++, how can we implement this program? I've checked and found that abstract class in C++ cannot be used to declare variables like UShape myshape. Can we use other methods to implement a class like bucket with an interface variable?

Upvotes: 0

Views: 151

Answers (3)

Mike Dinescu
Mike Dinescu

Reputation: 55760

Maybe I misunderstood your question but there is no reason why you couldn't declare a private member of the abstract class type. The following should be similar to your Java example:

class UShape {
  public:
     virtual void setWidth (int w) =0;
     virtual void setHeight (int h) =0;
     virtual int getArea() =0;
     virtual ~UShape() =0;
};

class Rectangle: public UShape {
  private:
     int width;
     int height;
  public:
     void setWidth (int w) { this.width = w; }
     void setHeight (int h) { this.height = h; }
     int getArea (void) { return (width * height); }
};

class Triangle: public UShape {
  private:
     int width;
     int height;
  public:
     void setWidth (int w) { this.width = w; }
     void setHeight (int h) { this.height = h; }
     int getArea (void) { return (width * height) / 2; }
};

class bucket{
  private: 
    std::unique_ptr<UShape> myshape;

  public:

    //do something with myshape
    void defineShape(int i){
       if (i == 1){
          myshape = std::make_unique<Rectangle>();
          myshape->setWidth(5);
          myshape->setHeight(5);
       }
    }
    void printArea(){
        cout << myshape ? myshape->getArea() : 0;
    }

}

int main () {
   bucket b();
   b.defineShape(1);
   b.printArea();
}

Upvotes: 3

Naveen Mani
Naveen Mani

Reputation: 21

I am going to use the same idea as Mike's but instead use C++11 and C++14 primitives for memory management ie. cleanup the memory allocated to the pointers without explicitly calling delete operator.

class UShape {
    public:
    virtual void setWidth (int w) =0;
    virtual void setHeight (int h) =0;
    virtual int getArea() =0;
};

class Rectangle: public UShape {
     private:
         int width;
         int height;

     public:
         void setWidth (int w) { this.width = w; }
         void setHeight (int h) { this.height = h; }
         int getArea (void) { return (width * height); }
};

class Triangle: public UShape {
    private:
        int width;
        int height;
    public:
        void setWidth (int w) { this.width = w; }
        void setHeight (int h) { this.height = h; }
        int getArea (void) { return (width * height) / 2; }
};

class bucket{
    private: 
        std::unique_ptr<UShape> myshape; //c++11

    public:
         //do something with myshape
        void defineShape(int i){
            if (i == 1){
                myshape = std::make_unique<Rectangle>(); //C++14 
                myshape->setWidth(5);
                myshape->setHeight(5);
            }
        }
void printArea(){
    cout << myshape->getArea();
}

}

int main () {
    std::unique_ptr<bucket> b(new bucket()); //c++11
    b->defineShape(1);
    b->printArea();
}

Upvotes: 1

Anton Savin
Anton Savin

Reputation: 41331

In C++ you have to use pointers to base class, or better, smart pointers like shared_ptr or unique_ptr:

class bucket{
private:
    std::unique_ptr<UShape> myshape;

public:
    //do something with myshape
    void defineShape(int i){
        if (i == 1){
            myshape = std::make_unique<Rectangle>();
            myshape->setwidth(5);
            myshape->setHeight(5);
        }
    }

    void printArea(){
        std::cout << myshape->getarea() << std::endl;
    }
};

int main() {
    bucket b;
    b.defineShape(1);
    b.printArea();
}

In some scenarios references are also helpful:

Rectangle r;
UShape& shape = r;
std::cout << shape.getarea() << std::endl;

Upvotes: 0

Related Questions