First of all the way you defined class Square will not compile because it implicitly calls the default constructor of the parent class Rectangle. The default constructor of Rectangle was not generated and so you either have to define it(1) or change the constructor initializer of the class Square(2)
1.
class Rectangle {
...
public:
Rectangle() = default;
};
class Square : public Rectangle {
public:
Square(int s): Rectangle(s,s) {}
};
The object of type Rectangle remains a Rectangle object even after you down-cast a pointer to it to a Square pointer. Falsely casting a pointer to a base class (that actually points to an instance of the base class) to a pointer of the derived class and then using it will cause undefined behavior. (see code in the last code snippet below after "2. wrong cast")
But in case you actually created a Square object and use a base pointer to refer to it as in:
Rectangle* rect = new Square(5);
And then you need to access some Square specific functionality so you would like to down-cast Rectangle* to Square* then there are 2 ways.
Dynamic casting using
Square* square = dynamic_cast<*Square>(rect);
square->square_method(); // perhaps not available in the base class public interface
This will not work in our case because it uses run-time type information available only for classes which have an abstract base class (polymorphic classes). To make it work we would have to make one of the methods of Rectangle virtual.
static cast (unsafe cast)
This way we down-cast
Square* square = static_cast<*Square>(rect);
square->square_method();
but the base class (as opposed to the dynamic_cast case) must not be abstract. So no virtual methods. Also we have to be 100% sure that the original rect pointer was pointing to an instance of Square.Otherwise we are just fooling the compiler and we get undefined behavior.
#include <iostream>
#include <vector>
class Rectangle {
private:
int h_, w_;
public:
Rectangle(int h, int w): h_(h), w_(w) {}
};
class Square : public Rectangle {
public:
Square(int s): Rectangle(s,s) {}
void special_func(){
std::cout << "special square logic";
}
};
int main() {
// 1. proper usage
Rectangle* rect = new Square(5);
Square* square = static_cast<Square*>(rect);
square->special_func();
// rect->special_func(); class Rectangle' has no member named 'special_func'
// 2. wrong cast
Rectangle* actual_rect = new Rectangle(5,10);
Square* not_square = static_cast<Square*>(rect);
not_square->special_func(); // seems to work but is actually Undefined Behavior
delete rect;
delete actual_rect;
}