0

I am new to inheritance and I am having trouble grasping some of its concepts.

What I am trying to do is I have a class called Rectangle which creates and draws a rectangle. I have another class called Button which is a rectangle that has text on it and changes color depending on whether it is clicked or not.

My Rectangle class is used in other areas and works. I'm not sure how to get the Button class to inherit from the Rectangle class the way I want it to.

Rectangle.h

#ifndef _rectangle_h_
#define _rectangle_h_
#include <vector>
#include "glut.h"

class Rectangle
{
public:
    Rectangle(std::vector<int> p1, std::vector<int> p2, double color[3]);
    void Draw() const;

protected:
    std::vector<int> mP1;
    std::vector<int> mP2;
    double mColor[3];
};

#endif

Rectangle.cpp

#include "Rectangle.h"

Rectangle::Rectangle(std::vector<int> p1, std::vector<int> p2, double color[3])
{
    mP1 = p1;
    mP2 = p2;

    mColor[0] = color[0];
    mColor[1] = color[1];
    mColor[2] = color[2];
}


void Rectangle::Draw() const
{
    glColor3d(mColor[0], mColor[1], mColor[2]);

    glBegin(GL_QUADS);
    glVertex2d(mP1[0], mP1[1]);
    glVertex2d(mP2[0], mP1[1]);
    glVertex2d(mP2[0], mP2[1]);
    glVertex2d(mP1[0], mP2[1]);
    glEnd();
}

Here is what I am trying to do but I am not sure what the correct syntax would be. Button is able to use Rectangle's points (mP1 and mP2) and color (mColor). Buttoncan't inherit Rectangle's Draw method because the Button must also draw the text, but it does need to call Rectangle's Draw method in order to draw the actual rectangle.

My question is "How would I go about doing this?"

Again, below is how I think the correct method of implementing this would be, but I know that it is incorrect and am asking what the correct way of doing it would be.

Button.h

#ifndef _button_h_
#define _button_h_

#include <vector>
#include <string>
#include "Rectangle.h"

class Button: public Rectangle
{
public:
    Button(std::vector<int> p1, std::vector<int> p2, std::string text);
    void Press();
    void Release();
    void Draw() const;

private:    
    bool mPressed;
    std::string mText;
};

#endif

Button.cpp

#include "Button.h"
#include <iostream>

Button::Button(std::vector<int> p1, std::vector<int> p2, std::string text)
{
    double color[3] = {.19,.75,1};
    Rectangle(p1,p2,color);
    mText = text;
}

void Button::Press()
{
    mPressed = true;

    mColor[0] = .19;
    mColor[1] = .34;
    mColor[2] = 1;
}

void Button::Release()
{
    mPressed = false;

    mColor[0] = .19;
    mColor[1] = .75;
    mColor[2] = 1;
}

void Button::Draw() const
{
    Rectangle::Draw();

    // I will worry about drawing the actual text later
    // for now I just want to make sure that I can print the text
    std::cout << mText << std::endl;  
}
tysonsmiths
  • 485
  • 1
  • 8
  • 19
  • You should probably rephrase. There is no actual question here. – dingalapadum Apr 12 '15 at 03:29
  • make `Rectangle::Draw` virtual (and override it)? – Kevin Apr 12 '15 at 03:34
  • The way you are doing it is called composition(http://en.wikipedia.org/wiki/Object_composition). Which probably the right thing to do in this case. Inheritance is used differently see (http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)). A `button` is a abstract thing which might _have a_ rectangle (a button could be round or a triangle). It _isn't_ a rectangle – dingalapadum Apr 12 '15 at 03:34
  • So what your saying to do is to have `Button` create an instance of `Rectangle` and have it stored as a data member? – tysonsmiths Apr 12 '15 at 03:49
  • Pass vectors and strings by const reference to avoid copies. – Neil Kirk Apr 12 '15 at 03:58
  • @byurocks23: In short: Yes. I'm not saying that you can't use inheritance. I'm just saying, that I don't think that it is a very good design. You might want to have a look at the more extended discussion: http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance. The current implementation as you have it is strange in any case since button is inheriting from rectangle _and_ having rectangle as a member. – dingalapadum Apr 12 '15 at 12:11

3 Answers3

2

As a beginner you should observe these rules religiously:

  1. Every inheritable class must have a virtual destructor.
  2. Every overridable method must be virtual.

The syntax for invoking a parent constructor is as follows:

Button::Button (std::vector<int> p1, std::vector<int> p2, std::string text) :
    Rectangle (p1, p2, color)
{
   // rest of Button constructor
}

You need to define color as a static member of Button.

It is recommended to define classes for Color and Point rather than use naked arrays/vectors. std::vector for a 2d point is an overkill. Use std::array or just class Point {int x, y; ...};

Whether inheritance is appropriate in your case or not is debatable. Perhaps if the rectangle-ness of your Button is only used fir drawing it, then inheritance is not appropriate. Such a button merely uses a rectangle to draw itself. OTOH if boundaries of your objects are rectangles and these boundaries are used for object interaction, e.g. for computing an object that contains other smaller objects, then inheritance is most appropriate.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
0

You need to write a default constructor in Rectangle to create an object of Button, because when you try to create an object of Button, it will try to call base class constructor. Otherwise you need to change the constructor definition of derived class constructor by calling base class constructor in initialization list.

Now you are overriding the function draw() in button. If you prefer to use polymorphism, to call a function using base class pointer, you should define Rectangle::draw() should be defined as a virtual function.

Steephen
  • 14,645
  • 7
  • 40
  • 47
  • I hope I am understanding what your saying. "write a default constructor in Rectangle to create an object of Button" The problem with this is I use `Rectangle` in other places so I wouldn't necessarily want to create a `Button` when I am using a `Rectangle` under different circumstances. Along with this, would making `Rectangle::draw()` virtual cause `Button` to be called every time I want to draw a `Rectangle`? Because again, I use `Rectangle` in other circumstances. – tysonsmiths Apr 12 '15 at 03:46
  • With the suggested changes , you can create Rectangle whenever you want. Default constructor of Rectangle do not have any arguments. If you create a Rectangle by passing arguments, it will call the constructor of Rectangle which has matching parameters. For your second question, if you assign a button object pointer on Rectangle pointer then only polymorphism will come into picture. So how you are going to create your object is important, I mean what are all parameters passing to the constructor and which class is initializing is important to decide the impact of polymorphism. – Steephen Apr 12 '15 at 03:53
-1

Buttoncan't inherit Rectangle's Draw method because the Button must also draw the text, but it does need to call Rectangle's Draw method in order to draw the actual rectangle.

If you want to call the superclass draw method do Rectangle::Draw()

NJGUY
  • 2,045
  • 3
  • 23
  • 43