-3

I have this code:

#include <iostream>

using namespace std;

class Polygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
     int area ()
      { return 0; }
    void set2_values (int,int);
    virtual bool incompressible() const = 0;
};

bool Polygon::incompressible() const {
    return 1;
}

void Polygon::set2_values (int x, int y) {
  width = x;
  height = y;
}

class Rectangle: public Polygon {
  public:
    int area ()
      { return width * height; }
    virtual bool incompressible() const {
        return 1;
    }
};

class Triangle: public Polygon {
  public:
    int area ()
      { return (width * height / 2); }
    bool incompressible() const {
        return 0;
    }
};

int main () {
  Rectangle rect;
  Triangle trgl;
  Polygon poly;
  Polygon * ppoly1 = &rect;
  Polygon * ppoly2 = &trgl;
  Polygon * ppoly3 = &poly;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  ppoly3->set_values (4,5);
  ppoly3->set2_values (4,5);
  //ppoly3->incompressible();
  cout << ppoly1->area() << '\n';
  cout << ppoly3->incompressible() << '\n';
  cout << ppoly2->area() << '\n';
  cout << ppoly3->area() << '\n';
  return 0;
}

I am getting an error:

cannot declare variable 'poly' to be of abstract type 'Polygon' because the following virtual functions are pure within 'Polygon': virtual bool Polygon::incompressible() const

Can anyone explain why I am getting this error?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Aparna
  • 57
  • 5
  • 3
    Dont use stuff that you do not understand. More positively: make sure you understand the stuff that you use. Why did you write this: `virtual bool incompressible() const = 0;` ? Do you know what an abstract method is? Do you know what it means for a class to be abstract? If you dont want the class to be abstract, then dont make it abstract :P – 463035818_is_not_an_ai Oct 27 '16 at 18:11
  • 2
    Just as the compiler told you for `Polygon poly;` You cannot create an instance of an abstract class. If you remove all the offending code, your [stuff](http://coliru.stacked-crooked.com/a/64d3bcdd7f4c2bdf) just works fine. – πάντα ῥεῖ Oct 27 '16 at 18:12
  • There is no rule saying that we cant have an abstract method and then later add definition to it. In the header file Eg: virtual bool transfersMass(const phaseModel& phase) const = 0; In the C file : bool Foam::twoPhaseSystem::transfersMass() const { return transfersMass(phase1()); } – Aparna Oct 27 '16 at 18:15
  • 4
    @Aparna -- The problem is that you're trying to *instantiate* an abstract class. Do you know what *instantiate* means? Plain and simple, you can't do this: `Polygon poly;`. – PaulMcKenzie Oct 27 '16 at 18:18
  • @Paul -- Hi Paul. But since I am adding definition to the incompressible function it does not make the Polygon class to be abstract anymore. So I can instantiate the class. – Aparna Oct 27 '16 at 18:42
  • 1
    If the virtual function has `= 0", it's still pure virtual and the class is still abstract, even if you provide a definition. See this: http://stackoverflow.com/q/2089083/10077 – Fred Larson Oct 27 '16 at 18:46
  • @Aparna No. It will always be abstract. You don't make it "unabstract" by giving the function a body. – PaulMcKenzie Oct 27 '16 at 18:57
  • @FredLarson so when I have a virtual function declared as =0 and then although if I have the definition for it defined in the same base class it is still an abstract class. Am I correct.? – Aparna Oct 27 '16 at 18:57
  • You probably need to read a book. Unfortunately, SO is not a tutorial site. – SergeyA Oct 27 '16 at 18:59
  • @FredLarson I have one more question. Suppose I have the following structure (File A where I included the header of file B. Now in File B I have a couple of abstract methods the definitions of which are provided in the derived classes of class B. I a trying to instantiate File A which fails indicating(because the virtual methods are pure within) I understand this e. So I went ahead and included the path for the derives classes in the Make/options folder of file A. Still the same error pops up. – Aparna Oct 27 '16 at 19:02
  • 1
    @Aparna: a method is abstract if it uses `virtual = 0`, period. The class *may* provide a default body implementation that derived classes can call if they want to, thus allowing derived classes to share common code, but the method itself, and thus the class it belongs to, are still abstract, so you cannot instantiate instances of that class, only of derived classes that override the abstract method. – Remy Lebeau Oct 27 '16 at 19:16

1 Answers1

2

The error is self-explanatory. Polygon is an abstract class, because its incompressible() method is abstract. Polygon is providing a default body implementation for incompressible(), but that does not change the fact that incompressible() is declared as abstract in the Polygon class definition.

As such, you simply cannot instantiate an object instance of the abstract Polygon class directly. But that is exactly what your poly variable is trying to do.

You must instantiate a descendant of Polygon that overrides incompressible() so it is not abstract anymore. Which means changing your poly variable to be a Rectangle or Triangle instead of a Polygon. Or just get rid of poly, since your other variables are doing an adequate job of demonstrating the polymorphic nature of the Polygon descendants.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I have one more question. Suppose I have the following structure (File A where I included the header of file B. Now in File B I have a couple of abstract methods the definitions of which are provided in the derived classes of class B. I a trying to instantiate File A which fails indicating(because the virtual methods are pure within) I understand this e. So I went ahead and included the path for the derives classes in the Make/options folder of file A. Still the same error pops up. – Aparna Oct 27 '16 at 19:25
  • @Aparna: (please don't repeat comments. I saw your same comment further above) Simply adding source files to your project doesn't change your *declarations* in the header files. You are clearly still using abstract classes the wrong way. Rather than *describing* your structure, please [edit your question](http://stackoverflow.com/posts/40291445/edit) to *show the actual code* you are having trouble with. – Remy Lebeau Oct 27 '16 at 19:26
  • 2
    @Aparna You're making this much more harder than it seems. If the class has pure virtual functions, you *cannot* instantiate that class. It doesn't matter how you've got things configured, one pure virtual function makes that class abstract and you can't instantiate it. You can't "trick" C++ into instantiating an abstract class. – PaulMcKenzie Oct 27 '16 at 19:28
  • Okay. I got it. Thank you so much for both of you for patiently explaining me. Thanks..!! – Aparna Oct 27 '16 at 20:20