You can declare the variable a Triangle*
not a Shape*
, this way you'll have access to the derived class and base class methods and variables:
int main()
{
Triangle* sh = new Triangle();
Square* sh2 = new Square();
std::cout << sh->getArea() << std::endl; //3
std::cout << sh2->getArea() << std::endl; //16
std::cout << sh->sideA << std::endl; //3
std::cout << sh2->sideA << std::endl; //4
delete sh;
}
To use delete sh
safely you should have a virtual destructor
class Shape
{
public:
virtual double getArea() = 0;
virtual ~Shape(){} //virtual destructor
};
Since you already have an abstract class, why not use it to access the the data in the derived classes:
Here is how I would do it:
#include <iostream>
#include <memory>
class Shape
{
private:
double sideA; //shared members can be defined in base class, assuming all
//derived classes will have sideA member
protected:
Shape(double sideA) : sideA(sideA) {}//for initialization of sideA in derived classes
public:
Shape() = default;
virtual double getArea() = 0;
double getSideA() { //shared logic
return sideA;
}
virtual ~Shape(){} //virtual destructor
};
class Triangle : public Shape
{
private:
double height = 2; //specific property
public:
Triangle() : Shape(3) {} //intialize sizeA
double getHeight(){ //specific method, must instanciate Triangle to access
//for collections it's best to use interface method like getArea()
return height;
}
double getArea() override {
return 0.5 * getSideA() * height;
}
};
class Square : public Shape
{
public:
Square() : Shape(4) {} //intialize sizeA
double getArea() override {
return getSideA() * getSideA();
}
};
int main()
{
std::unique_ptr<Shape> sh(new Triangle); //smart pointer
std::unique_ptr<Shape> sh2(new Square); //smart pointer
std::cout << sh->getArea() << std::endl; //3
std::cout << sh2->getArea() << std::endl; //16
std::cout << sh->getSideA() << std::endl; //3
std::cout << sh2->getSideA() << std::endl; //4
//delete sh; //no need, smart pointer
}
Take a look at smart pointers.