2

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?

programmer
  • 27
  • 4
  • 5
    you mean `foo(Rect)`? Derived classes are implicitly convertible to its base classes. Just be careful about object slicing if passing by value instead of a reference. – Quimby Mar 24 '21 at 14:38
  • Your inheritance is set up backwards. What I mean is the content of your classes. – sweenish Mar 24 '21 at 14:38
  • `foo` does not take a pointer. Anyhow, what happened when you called `foo(Rect);` ? – 463035818_is_not_an_ai Mar 24 '21 at 14:39
  • 1
    Just pass `Rect` to `foo`. It's a feature of inheritance that you can pass a derived object to a function taking a reference to the base. – NathanOliver Mar 24 '21 at 14:39
  • 1
    "Every shape has a width and a height, but only rectangles have an area"? – molbdnilo Mar 24 '21 at 14:41
  • 4
    Note that `Shape()` in your `Rectangle` constructor does not initialize the base subobject, but creates an unnamed `Shape` instance that is immediately discarded. The default initialization happens automatically - you don't need to do anything. I would recommend a visit to the [book list](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – molbdnilo Mar 24 '21 at 14:44
  • `function foo(Shape &s)` - you mixed some js in there. Or did you mean to return an instance of type `function`? Whatever it might be. – Lukas-T Mar 24 '21 at 14:53
  • The rect and shape classes were from sample code that I took from the c++ inheritance documentation. I used this to simplify my actual problem, but when I try to pass in the inherited class, I get an error saying "cannot cast 'inherited_class_named' to its private base class 'base_class_name'. – programmer Mar 25 '21 at 03:06

1 Answers1

-2

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.

sweenish
  • 4,793
  • 3
  • 12
  • 23