Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
In the following code in main function, shape is declared as a pointer to class Shape object but the address of object of class Rectangle namely rec is saved in the following line.Can somebody please tell me where I am wrong in my understanding.
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
return (width * height / 2);
}
};
int main( )
{
Shape *shape;//pointer to Shape class
Rectangle rec(10,7);
Triangle tri(10,5);
shape = &rec;//address of Rectangle class object saved
shape->area();
shape = &tri;
shape->area();
return 0;
}
Shape needs to declare area as virtual to get polymorphic behaviour.
virtual int area()
{
...
}
Your code has several errors and as the result the code has no a sense.
Consider for example constructor
Triangle( int a=0, int b=0)
{
Shape(a, b);
}
Ar first the default constructor of Shape will be called because you did not specify a call of the Shape constructor in the ctor initialization list. So width and height will be set to zero by the default constructor.
Inside the body of constructor of Triangle you simply create a temporary object of type Shape that will be used never.
It could look the dollowing way
Triangle( int a=0, int b=0) : Shape( a, b ) {}
or even as
explicit Triangle( int a=0, int b=0) : Shape( a, b ) {}
if you know what explicit means.
Apart from this the class hierarchy shall be based on virtual functions that you could get the effect of the polimorphism. So class Shape should be defined the following way
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0) : width( a ), height( b ) {}
virtual ~Shape() {}
virtual int area() const = 0;
};
int Shape::area() const
{
cout << "Parent class area :" <<endl;
return 0;
}
And uodate the derived classes according to these changes.
Rectangle is derived from Shape, see the line
class Rectangle: public Shape
This is called inheritance or an "is-a" relation: a Rectangle is a Shape. Therefore, a Shape* can point to a rectangle. More info, can, for example, be found in Base class pointer vs inherited class pointer? or most C++ tutorials covering inheritance.
As Roddy's answer notes, however, you should declare area in Shape as virtual, otherwise calling shape->area() will always call Shape's area method instead of the overridden method provided by Rectangle. Since area for Shape does not really make sense, you might even consider declaring it as pure virtual:
virtual int area() = 0;
Related
I understand that you can access members of the base class from a derived class, however, I have a function that requires a pointer to my base class as a whole. For example:
#include <iostream>
using namespace std;
function foo(Shape &s){
//does something
}
// Base class
class Shape {
public:
Shape(int w = 100, int h = 100){
width = w;
height = h;
}
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
protected:
int width;
int height;
};
// Derived class
class Rectangle: public Shape {
public:
Rectangle(){
Shape();
}
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
foo(// Pointer Reference to Rect.Shape here);
return 0;
}
Is there any way to get a pointer to this base class from the derived class?
Here's a working version of your code. I made some changes to it and added comments to explain the changes. Your program requires polymorphism to behave as expected, otherwise you'll 'slice' your derived object and just have a Base object.
#include <iostream>
#include <string>
// Base class
// Your base should only have things that would be common to all derived classes
// Consider what the width and height of a Circle would be
//
// You may not have gotten to virtual functions and polymorphism yet. This is
// how you would set up an interface for your Derived classes. I am requiring
// any derived class to implement getArea() and identify() if it wants to be a
// 'concrete' class. Otherwise it will be abstract, which means you can't
// declare objects of that type. It is not possible to declare a Shape object
// because of the pure virtual functions
class Shape {
public:
virtual ~Shape() = default; // A virtual destructor is required
virtual double getArea() const = 0; // Pure virtual function
virtual std::string identify() const = 0;
};
// Derived class
class Rectangle : public Shape {
public:
// The base class should be initialized in the constructor's
// initialization section. What you did was declare a temporary Shape that
// went away when the function ended.
// All class data should be set in the initialization section
Rectangle(int w, int h) : Shape(), width(w), height(h) {}
double getArea() const override { return (width * height); }
std::string identify() const override { return "Rectangle"; }
private:
int width = 0;
int height = 0;
};
// A new derived class that should work (a circle **is-a** shape), but doesn't
// with your setup. Circles don't have width and height
class Circle : public Shape {
public:
Circle(int r) : Shape(), radius(r) {}
double getArea() const override { return 2 * 3.14 * radius * radius; }
std::string identify() const override { return "Circle"; }
private:
int radius = 0;
};
// Subjective, I moved the function below the class definitions and added a body
void foo(Shape &s) {
std::cout << "A " << s.identify() << " with area " << s.getArea() << ".\n";
}
int main(void) {
Rectangle rect(5, 3);
foo(rect);
Circle circ(4);
foo(circ);
return 0;
}
Output:
A Rectangle with area 15
A Circle with area 100.48
If I remove all the virtual stuff, a lot of things stop working. I now have to provide implementations for the Shape functions. That logically doesn't make much sense. And while I can pass my derived objects to foo(), they get sliced, and the filler Shape data gets printed instead.
I'm learning about c++ polymorphism. In the code below, a pointer called shape of the type of the base class Shape is creates and then pointed at the objects r and c.
The functions printArea(r); and printArea(c); are then called. However, at the point that these functions are called shape is pointing to the address of c. So how does it work when you call printArea(r);?
#include<iostream>
using namespace std;
class Shape {
public:
virtual float getArea() const = 0;
};
class Rectangle : public Shape {
private:
float width;
float height;
public:
Rectangle(float width, float height) : width(width), height(height) {}
float getArea() const {return width * height;}
};
class Circle : public Shape {
private:
float radius;
public:
Circle(float radius) : radius(radius) {}
float getArea() const {return 3.14159f * radius *radius;}
};
void printArea(const Shape& shape) {
std::cout << "Area: " << shape.getArea() << std::endl;
}
int main() {
Rectangle r(2,6);
Shape* shape = &r;
Circle c(6);
shape = &c;
printArea(r);
printArea(c);
printArea(*shape);
return 0;
}
I would guess your question is how, technically, is the call to getArea dispatched at run time.
The C++ standard does not prescribe this. It prescribes exactly which implementation must be executed, but not how that is accomplished.
Nearly all extant C++ implementations do that by placing a hidden pointer in each object of class with one or more virtual functions. That hidden pointer points to a table of function pointers, namely pointers to the virtual methods of the class of the object's dynamic type. This is called a vtable. And in general the call is dispatched by checking the object's vtable pointer, and retrieving the function pointer from the getArea item in the vtable, and calling that function.
There are complications for multiple inheritance, but those are just that: complications.
An alternative could be to search up the base class chain for each call.
That would be less efficient but still it's been used, at least in other languages, e.g. in original Smalltalk, and in Borlands GUI class framework for Pascal in Windows in the 1990s.
Another alternative is to place pointers to each virtual function directly in each object, essentially a vtable in each object. That approach is sometimes used in C. The main advantage is that it's conceptually simple. It also avoids one indirection. But it wastes space and doesn't generalize very well.
#include<iostream>
using namespace std;
class Shape {
public:
virtual float getArea() const = 0;
};
class Rectangle : public Shape {
private:
float width;
float height;
public:
Rectangle(float width, float height) : width(width), height(height) {}
float getArea() const {return width * height;}
};
class Circle : public Shape {
private:
float radius;
public:
Circle(float radius) : radius(radius) {}
float getArea() const {return 3.14159f * radius *radius;}
};
void printArea(const Shape& shape) {
std::cout << "Area: " << shape.getArea() << std::endl;
}
int main() {
Rectangle r(2,6);
Shape* shape = &r; // shape stores the address of object r which when further call
std::cout<< shape <<endl; //called sends its address
Circle c(6);
shape = &c; // same as r is being processed
std::cout<<shape<<endl;
printArea(r); // same thing is taking place here reference is passed and then polymorphism come
printArea(c); // into play
printArea(*shape); // as the shape was given reference of c in the end it returns its value
return 0;
}
if u still have any questions feel free to ask in comments!
I'm currently learning about C++ Inheritance, so if this question is a dumb one, I apologize in advance.
Implementing this scenario:
A super class has a color attribute, which can be any color (let's assume color is represented by an integer).
Let's assume I have an initialization of this super class, with the color red.
I am also going to initialize different objects of a sub-class which also share the color red.
My question is, is there any way that I can initialize this attribute color to red (or any color for that matter) and it would be automatically inherited by objects of it's sub-class, instead of setting the attribute to red every-time I initialize one of these objects?
Again apologies if I'm missing a basic concept here, but I can't seem to find anything online on this.
Pseudo-Code per request:
Super-class code:
class Shape {
int color;
Shape::Shape(int c) : color(c) { } //constructor
}
Sub-Class code:
class Square {
int length, width;
Square::Square(int l, int w, int c)
: length(l),
width(w),
color(c)
{ }
}
class Circle {
int radius;
Square::Square(int r, int c)
: radius(r),
color(c)
{ }
}
What I'm trying to say is that both square and circle need to have the same color, is there anyway (maybe from the super class? ) to declare this color (ex. red), and both shapes would have this color set the same?
You could accomplish what you want with a static default_color that gets used when no color is explicitly specified, and gets set whenever a color is specified.
struct Shape {
static int default_color;
int color;
Shape(int c) : color(c)
{
default_color = c;
}
Shape() : color(default_color) {}
};
Shape::default_color = BLACK;
struct Square : public Shape {
int length, width;
Square(int l, int w, int c)
: Shape(c),
length(l),
width(w),
{ }
Square(int l, int w)
: length(l),
width(w)
{ }
}
struct Circle : public Shape {
int radius;
Circle(int r, int c)
: Shape(c),
radius(r)
{ }
Circle(int r)
: radius(r)
{ }
}
int main()
{
Square sq(2, 3, RED);
Circle cir(10); // Automatically red, since that's
the last color explicitly specified
}
I would say this is a poor design though. Global state like this makes it very easy to make mistakes. You now have to think about the state of the entire program whenever you create a shape. It would be better to simply create the Circle as Circle cir(10, sq.color);. That makes it explicit what color your Circle is, and reduces cognitive load on the programmer.
Prior to C++11, the primary way to do this would be as follows:
class baseClass
{
int color;
baseClass() { color = RED; }
};
class subClass : public baseClass
{
subclass() { }
};
With C++11 and later, you can assign the default value in the class declaration:
class baseClass
{
int color = RED;
baseClass() { }
};
This would be inherited.
EDIT: As mentioned below, the default baseClass constructor is automatically called in this case.
There's a difference between a class and an instance of a class. A class is something like a structure, according to which further instances will be created. A class is something like a description, an instruction how to build objects. Inheritance is related to classes, not to objects. As for fields, the inherited class has all the same fields from the parent class plus some new fields you may add.
A simple example for you:
class MyBase {
public:
int color;
};
class MyChild : public MyBase {
public:
double length;
}
int main() {
MyBase myBaseObj;
myBaseObj.color = 1;
MyChild myChildObj;
myChildObj.color = 2;
myChildObj.length = 3.14;
return 0;
}
is there anyway (maybe from the super class? ) to declare this color (ex. red), and both shapes would have this color set the same?
In your posted example, yes. A super-class constructor can set its variables to whatever it wants to, for example:
Shape::Shape(int c) : color(7) { } // 7 == RED
If Shape had that constructor defined, then instances of every subclass would represent red shapes.
This sample program prints 7, overriding the user's chosen color:
#include <iostream>
class Shape {
public:
int color;
Shape(int c) : color(7) { } //constructor
};
class Square : public Shape {
public:
int length, width;
Square(int l, int w, int c)
: Shape(c),
length(l),
width(w)
{ }
};
class Circle : public Shape {
public:
int radius;
Circle(int r, int c)
: Shape(c),
radius(r)
{ }
};
int main() {
Square q(4,8,0);
std::cout << q.color << "\n";
}
In C++, I have two separate base classes, each of whose derived classes are somewhat coupled. Here's an example for the kind of thing I'd like to do:
First define a set of classes, e.g.,:
class Shape
{
public:
double area;
double diameter;
};
class Rectangle : public Shape
{
public:
double width;
double height;
};
class Circle : public Shape
{
public:
double radius;
};
The second set of classes then pertains to operations being performed on this first set of classes, something like this:
class Calculator
{
public:
static Calculator *create_calculator(shape *shape,const char *shape_type); // the factory
virtual void calculate()=0; // the actual calculation
};
class area_circles : public Calculator
{
class circles *circle;
public
area_circles(circles *circle)
{
this->circle = circle;
}
void calculate()
{
this->area = PI*pow(circle->radius,2);
}
}
class area_rectangles : public Calculator
{
class rectangles *rectangle;
public
area_rectangles(rectangles *rectangle)
{
this->rectangle = rectangle;
}
double calculate()
{
this->area = rectangle->height * rectangle->width;
}
}
Calculator *Calculator::create_calculator(shape *shape, const char *shape_type)
{
if (shape_type=="circle")
return new area_circles(shape);
if (shape_type=="rectangle")
return new area_rectangles(shape);
}
Then, the idea would be to call all this using something like:
rectangles *my_rectangle;
Calculator *area_calculator;
area_calculator = area_calculator->create_calculator(my_rectangle, "rectangle");
area_calculator->calculate();
However, this doesn't compile and I get an error (quite sensibly) pointing out how the Shape class has no member "width", and that "a value of type "shape *" cannot be assigned an entity of type "rectangles". The error's pretty clear on why this code isn't working.
Would anyone know how to get the code here to do what I'm trying to do?
From a design perspective, I recognize that part of the problem is that the derived classes end up being coupled, so maybe there is a better way to try to decouple the calculator class from the shape class. But I'd like to at least try out this approach for a while as well in my implementation, and for that I need the code to compile.
I am not entirely sure what you are trying to achieve here but I think the more usual approach to it is something like this:
class Shape
{
public:
virtual ~Shape() {}
// concrete classes must implement this function
virtual double get_area() const = 0;
};
class Circle
: public Shape
{
double diameter;
public:
Circle(double diameter): diameter(diameter) {}
virtual double get_area() const
{
return M_PI * diameter * diameter / 4;
}
};
class Rectangle
: public Shape
{
double width;
double height;
public:
Rectangle(double width, double height): width(width), height(height) {}
virtual double get_area() const
{
return width * height;
}
};
int main()
{
Circle c(2);
Rectangle r(20, 40);
// use Shape references (or pointers) to invoke polymorphic behaviour
Shape& cs = c;
Shape& rs = r;
std::cout << "Area of circle : " << cs.get_area() << '\n';
std::cout << "Area of rectangle: " << rs.get_area() << '\n';
}
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
};
class Rectangle: public Polygon {
public:
int area()
{ return width*height; }
};
int main () {
Rectangle rect;
Polygon * ppoly1 = ▭
ppoly1->set_values (4,5);
cout << rect.area() << '\n';
return 0;
}
In above example, what does ppoly1 points to and how is this pointer not able to access rectangle class's function?
WHY ppoly1->area() is an error
Thanks!
The expression ppoly1->area() is an error because ppoly1 is typed to Polygon which has no area method declared. When C++ tries to evaluate this member it essentially starts at Polygon sees no member named area and hence issues an error
It sounds like you want to give the Polygon type the notion of an area method without an implementation (forcing the derived types to provide one). If that is the case then you should declare an un-implemented virtual method in Polygon
class Polygon {
...
virtual ~Polygon() { }
virtual int area() = 0;
};
Base classes know nothing about their derived classes. When a base class is being defined there is no yet any derived class.
Variable ppoly1 is of the type Polygon *. Class Polygon has no method area so the compiler issues the error.
If you want to use a common interface for derived classes you should declare it in the base class. For example
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area() const = 0;
virtual ~Polygon(){}
};
class Rectangle: public Polygon {
public:
int area() const
{ return width*height; }
};
int main () {
Rectangle rect;
Polygon * ppoly1 = ▭
ppoly1->set_values (4,5);
cout << rect.area() << '\n';
return 0;
}
ppoly1 is a Polygon pointer. The fact that the pointer points to a Rectangle object does not enable it to call Rectangle functions; the type is still Polygon*. To enable it to call Rectangle functions you need to either make it a Rectangle pointer, or implement a virtual method in your Polygon class,
e.g.
virtual int area() const;
This means that when a Polygon object has area() called on it, it will go looking for the most derived instance of area(). On ppoly1 this will be Rectangle->area(). You can keep your Rectangle code the same as before.
Wikipedia on virtual functions: http://en.wikipedia.org/wiki/Virtual_function