I am trying to make a Polygon class and a Rectangle and Triangle that inherit the first. Polygon class has height and width variables that I want them to be be given values within the constructor. Then, Rectangle and Triangle have area calculation methods. Then, I use a main() to give some examples. I use:
#include <iostream>
using namespace std;
class Polygon {
public:
Polygon(int, int);
protected:
int height;
int width;
};
class Rectangle: public Polygon {
public:
void calc_area();
};
class Triangle: public Polygon {
public:
void calc_area();
};
Polygon::Polygon(int a, int b) {
height = a;
width = b;
}
void Rectangle::calc_area() {
cout << "Rectangle area: " << (height*width) << endl;
}
void Triangle::calc_area() {
cout << "Triangle area: " << (height*width/2) << endl;
}
int main() {
Rectangle s1(5, 2);
Triangle s2(5, 2);
s1.calc_area();
s2.calc_area();
}
But while everything looks ok to my newbie eyes, I get a series of errors:
12 base Polygon' with only non-default constructor in class without a constructor `
36 no matching function for call to `Rectangle::Rectangle(int, int)
37 no matching function for call to `Triangle::Triangle(int, int)'
Can someone give me some tips? As seen, I am very new to C++...
You shouldn't call constructor to use ., such as:
Rectangle s1;
Triangle s2;
s1.Polygon(5, 2);
s2.Polygon(5, 2);
try this way:
Rectangle s1(5, 2);
Triangle s2(5, 2);
and you should add constructor for Rectangle and Triangle respectively:
class Rectangle: public Polygon {
public:
Rectangle(int height, int width):Polygon(height, width){}
void calc_area();
};
class Triangle: public Polygon {
public:
Triangle(int height, int width):Polygon(height, width){}
void calc_area();
};
To construct Triangle and Rectangle you are calling their invisible default constructors.
So the Triangle() and Rectangle() methods. These are implemented as empty methods, but they must also call the default constructors of any class they inherit from. So effectively this is the code that's being generated:
Triangle() : Polygon() {}
Rectangle() : Polygon() {}
Polygon will not get a default constructor because you created your own constructor. So the only way to get that back is to define it:
Polygon() {}
Or in C++11:
Polygon() = default;
The default constructor Triangle() or Rectangle() are called when you instantiate the member variable. So these lines are calling constructors:
Rectangle s1;
Triangle s2;
Note that once they are constructed they cannot be reconstructed. So these calls are illegal:
s1.Polygon(5, 2);
s2.Polygon(5, 2);
Now if you want to accomplish having a setting constructor, you can do that, but you'll need to define it for Triangle and Rectangle:
Triangle(int width, int height) : Polygon(width, height) {}
Triangle(int width, int height) : Polygon(width, height) {}
Again recall that defining these methods will cause your default constructor not to be generated for Triangle or Rectangle. So your s1 and s2 declarations will now be illegal, but that's OK cause you want to declare them with your new constructors anyway:
Rectangle s1(5, 2);
Triangle s2(5, 2);
You must use this way...
Rectangle *s1 = new Rectangle;
s1->ab(5,2);
s1->calc_area();
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.
Initializing fields within constructor works:
class Shape{
protected:
float width,height;
public:
Shape()
{
width = 13.2;
height = 3.2;
}
}
However when using a constructor with parameters, the code no longer compiles:
class Shape{
protected:
float width,height;
public:
Shape(float w, float h)
{
width = w;
height = h;
}
}
Triangle class:
class Triangle : public Shape{
public:
float area()
{
return (width * height / 2);
}
Here is the main function:
int main() {
Shape s = Shape();
Triangle tri;
std::cout << tri.area() << std::endl;
return 0;
This compiles and outputs result:
21.12
However when using constructor with parameters Shape s = Shape(13.2,3.2);
it seems the Triangle object tri can no longer access the width and height of Shape class.
The problem is that by defining Shape's constructor with arguments, you disable the default constructor of Shape (or more precisely, define it as deleted). And since Triangle does not define a default constructor, it also gets marked as deleted.
You need to either define the default constructor of Shape, or define a constructor of Triangle that will call the constructor of Shape with parameters w and h.
How to resolve not a member of base class when create derived object using new operator
When i execute the below program, i am getting the below error only when i create a object using new operator "shape *s=new Rectangle";. But i havent faced any issues when i create object "Rectangle s"
Actually i dont want to use hello method in my Triangle class. Need to acces/uses hello method in rectangle class by creating object using new operator "shape *s=new Rectangle".
Please let us know how to resolve this issue using new operator.
Error:
1>c:\shape\shape\shape.cpp(60) : error C2039: 'hello' : is not a member of 'Shape'
1>c:\shape\shape\shape.cpp(10) : see declaration of 'Shape'
Code snippet:
// Shape.cpp : Defines the entry point for the console application.
//
#include <iostream>
using namespace std;
// Base class
class Shape
{
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// Derived classes
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
void hello()
{
std:cout<<std::endl<<"hello"<<std::endl;
}
};
class Triangle: public Shape
{
public:
int getArea()
{
return (width * height)/2;
}
};
int main(void)
{
Shape *s= new Rectangle;
// Triangle Tri;
s->setWidth(5);
s->setHeight(7);
// Print the area of the object.
cout << "Total Rectangle area: " << s->getArea() << endl;
s->hello();
/*
Tri.setWidth(5);
Tri.setHeight(7);
// Print the area of the object.
cout << "Total Triangle area: " << Tri.getArea() << endl;
*/
return 0;
}
You have a pointer to Shape, but (and this is what your compiler tells you) Shape has no member hello().
So theres two ways to access it:
Either you cast it to Rectangle* first (which might fail for non-rectangles) or you create a function virtual void hello() in Shape which is then resolved at compile-time - for all classes that inherit from Shape.
I have created three class: Square, Rectangle and Polygon. Square is inheriting from Rectangle and Rectangle is inheriting from Polygon.
The problem is that whenever I call Square constructor, Rectangle constructor get called and I get an error. How can I solve this?
#include <iostream>
using namespace std;
// Multilevel Inheritance
class Polygon
{
protected:
int sides;
};
class Rectangle: public Polygon
{
protected:
int length, breadth;
public:
Rectangle(int l, int b)
{
length = l;
breadth = b;
sides = 2;
}
void getDimensions()
{
cout << "Length = " << length << endl;
cout << "Breadth = " << breadth << endl;
}
};
class Square: public Rectangle
{
public:
Square(int side)
{
length = side;
breadth = length;
sides = 1;
}
};
int main(void)
{
Square s(10);
s.getDimensions();
}
If I comment out the Rectangle constructor, everything works fine. But I want to have both constructors. Is there anything I can do?
You should not set members of a base class in a derived class constructor. Instead, call the base class constructor explicitly:
class Polygon
{
protected:
int sides;
public:
Polygon(int _sides): sides(_sides) {} // constructor initializer list!
};
class Rectangle: public Polygon
{
protected:
int length, breadth;
public:
Rectangle(int l, int b) :
Polygon(2), // base class constructor
length(l),
breadth(b)
{}
};
class Square: public Rectangle
{
public:
Square(int side) : Rectangle(side, side)
{
// maybe you need to do this, but this is a sign of a bad design:
sides = 1;
}
};
constructor should be
Square(int side) : Rectangle(side, side) { sides = 1; }
as Rectangle has no default constructor.
I am trying to derive class Smiley from Circle:
struct Smiley : Circle {
void draw_lines() const;
};
void Smiley::draw_lines() const {
Circle::draw_lines(); // outline
/*rest of code here*/
}
This is the definition of Circle:
struct Circle : Shape {
Circle(Point p, int rr); // center and radius
void draw_lines() const;
Point center() const;
void set_radius(int rr) { set_point(0, Point(center().x - rr, center().y - rr)); r = rr; }
int radius() const { return r; }
private:
int r;
};
I basically want a Circle with a couple arcs drawn on top. Theoretically, I should only have to write draw_lines() over (which is defined as virtual in Shape), but it does nothing without a constructor, and if I have a constructor, it get an error and says that Circle does not have a default constructor available, even if I have no code in the constructor relating to Circle.
Does anyone know why I am getting this error?
When you inherit from a class with no default constructor, you have to make sure you invoke the non-default one.
Otherwise your derived class tries to invoke that non-existent default constructor, as the error says. In this case, you can probably just pass the same arguments straight through.
struct Smiley : Circle {
Smiley(Point p, int rr);
void draw_lines() const;
};
Smiley::Smiley(Point p, int rr)
: Circle(p, rr)
{};
I basically want a Circle with a couple arcs drawn on top
Then it's not a circle any more, so why does Smiley inherit Circle?
You've defined a constructor for circle that requires a Point and a Radius. You should define one with identical parameters for Smiley, that invokes the base class constructor with those parameters, via a Member Initialiser List.
struct Smiley : Circle {
Smiley(Point p, int rr) : Circle(p, rr)
{
}
void draw_lines() const;
};