Confusion about inheritance and the allocating memory via new

T

tharringtonan

I am compiling the following code, main.cpp, as follows:
gcc main.cpp

I get the following compile error:
main.cpp: In function `int main()':
main.cpp:28: no matching function for call to `CPolygon::area()'


The code is listed below:


#include <iostream>
using namespace std;

class CPolygon {
public:
virtual void set_values (int a, int b) { width=a; height=b; };

protected:
int width, height;
};

class CRectangle: public CPolygon {
public:
int area () { return (width * height); };
};

int main ()
{
CPolygon * ppoly1 = new CRectangle;
ppoly1->set_values (4,5);
cout << ppoly1->area() << endl;
return 0;
}


Why does this not compile?
 
T

tharringtonan

I am compiling the following code, main.cpp, as follows:
gcc main.cpp

I get the following compile error:
main.cpp: In function `int main()':
main.cpp:28: no matching function for call to `CPolygon::area()'

The code is listed below:

#include <iostream>
using namespace std;

class CPolygon {
public:
virtual void set_values (int a, int b) { width=a; height=b; };

protected:
int width, height;
};

class CRectangle: public CPolygon {
public:
int area () { return (width * height); };
};

int main ()
{
CPolygon * ppoly1 = new CRectangle;
ppoly1->set_values (4,5);
cout << ppoly1->area() << endl;
return 0;

}

Why does this not compile?

I meant g++ not gcc.
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

I am compiling the following code, main.cpp, as follows:
gcc main.cpp

I get the following compile error:
main.cpp: In function `int main()':
main.cpp:28: no matching function for call to `CPolygon::area()'


The code is listed below:


#include <iostream>
using namespace std;

class CPolygon {
public:
virtual void set_values (int a, int b) { width=a; height=b; };

protected:
int width, height;
};

class CRectangle: public CPolygon {
public:
int area () { return (width * height); };
};

int main ()
{
CPolygon * ppoly1 = new CRectangle;
ppoly1->set_values (4,5);
cout << ppoly1->area() << endl;
return 0;
}

Because a CPolygon does not have a area()-method. Only CRectangle does.
Either declare ppoly1 as a pointer to a CRectangle, or add

virtual int area() = 0;

to CPolygon right under the declaration of set_values().

By the way, set_values is a really bad name, and probable a bad method
as well. Since it has polymorphic behaviour the user can know what
values it will set. Read up on the Liskov substitution principle to see why.
 
R

Robert Bauck Hamar

I am compiling the following code, main.cpp, as follows:
gcc main.cpp

I get the following compile error:
main.cpp: In function `int main()':
main.cpp:28: no matching function for call to `CPolygon::area()'


The code is listed below:


#include <iostream>

#include said:
using namespace std;

class CPolygon {
public:
virtual void set_values (int a, int b) { width=a; height=b; };

protected:
int width, height;
};

class CRectangle: public CPolygon {
public:
int area () { return (width * height); };
};

int main ()
{
CPolygon * ppoly1 = new CRectangle;

This creates a ppoly1 to be a pointer. It has two types:
Its _static_ type is pointer to CPolygon.
Its _dynamic_ type is pointer to CRectangle.

The difference between static and dynamic types, is that static types is
what the compiler knows at compile time. The dynamic type is a run time
property.
ppoly1->set_values (4,5);
cout << ppoly1->area() << endl;

Here you call a member function of *ppoly. To accomplish this, the compiler
searches only the static type of *ppoly, that is CPolygon, which has no
member 'area'.
return 0;
}


Why does this not compile?

If ppoly1 had been changed to point to a CPolygon object, what should have
happened then?
 
T

tharringtonan

#include <ostream>










This creates a ppoly1 to be a pointer. It has two types:
Its _static_ type is pointer to CPolygon.
Its _dynamic_ type is pointer to CRectangle.

The difference between static and dynamic types, is that static types is
what the compiler knows at compile time. The dynamic type is a run time
property.


Here you call a member function of *ppoly. To accomplish this, the compiler
searches only the static type of *ppoly, that is CPolygon, which has no
member 'area'.



If ppoly1 had been changed to point to a CPolygon object, what should have
happened then?

This is the explanation that I was looking for.

Here is my problem in general.

I am writing a molecular dyanmics code. The user of the program will
set in the input file the type of boundary conditions. The boundary
conditions are represented by objects in the code. The important fact
are that there are several types of boundary conditions and they all
share many similar methods. In addition each boundary condition has a
few distinct methods.

So I figured I would write a base class so I could reuse the methods
that are shared by the numerous boundary conditions. However, I seem
to have to declare the methods that aren't shared by the boundaruy
conditions as virtual ...=0 in the base class.
Is there any way around of having to declare the nonshared methods as
virtual ... = 0 in the base class?
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

This is the explanation that I was looking for.

Here is my problem in general.

I am writing a molecular dyanmics code. The user of the program will
set in the input file the type of boundary conditions. The boundary
conditions are represented by objects in the code. The important fact
are that there are several types of boundary conditions and they all
share many similar methods. In addition each boundary condition has a
few distinct methods.

So I figured I would write a base class so I could reuse the methods
that are shared by the numerous boundary conditions. However, I seem
to have to declare the methods that aren't shared by the boundaruy
conditions as virtual ...=0 in the base class.
Is there any way around of having to declare the nonshared methods as
virtual ... = 0 in the base class?

Use a pointer with the correct static type, or perhaps you can set those
values in the constructor?
 
B

BobR

[snip]
If ppoly1 had been changed to point to a CPolygon object, what should have
happened then?

This is the explanation that I was looking for.
Here is my problem in general.
I am writing a molecular dyanmics code. The user of the program will
set in the input file the type of boundary conditions. The boundary
conditions are represented by objects in the code. The important fact
are that there are several types of boundary conditions and they all
share many similar methods. In addition each boundary condition has a
few distinct methods.

So I figured I would write a base class so I could reuse the methods
that are shared by the numerous boundary conditions. However, I seem
to have to declare the methods that aren't shared by the boundaruy
conditions as virtual ...=0 in the base class.
Is there any way around of having to declare the nonshared methods as
virtual ... = 0 in the base class?

// ref: class CRectangle: public CPolygon {};

// - downcast -
CRectangle *pCR( dynamic_cast<CRectangle*>( ppoly1 ) );
if( pCR ){
cout << pCR->area() << endl;
} // if(*)

delete ppoly1; // see 'virtual ~CPolygon(){}' below
return 0;
} // main()
// output: 20

Are you aware that you can 'define' a 'pure virtual' (virtual ... = 0;)?

class CPolygon{ public:
// CPolygon( int a = 0, int b = 0 ) : width(a), height(b){}
virtual void set_values (int a, int b) { width=a; height=b; };

virtual int area () = 0;

virtual ~CPolygon(){} // it's a base class

protected:
int width, height;
};

// - definition must be outside the class declaration. -
int CPolygon::area(){ return 0; };

// you don't want to 'return width * height;' here, unless you insure
// they are initialised ( proper Ctor).

HTH.
 
J

Jim Langston

This is the explanation that I was looking for.

Here is my problem in general.

I am writing a molecular dyanmics code. The user of the program will
set in the input file the type of boundary conditions. The boundary
conditions are represented by objects in the code. The important fact
are that there are several types of boundary conditions and they all
share many similar methods. In addition each boundary condition has a
few distinct methods.

So I figured I would write a base class so I could reuse the methods
that are shared by the numerous boundary conditions. However, I seem
to have to declare the methods that aren't shared by the boundaruy
conditions as virtual ...=0 in the base class.
Is there any way around of having to declare the nonshared methods as
virtual ... = 0 in the base class?

As BobR has shown, the way to call a method in a derived class that is not
in the base class is by using dynamic_cast to the derived class and ensure
that the returned pointer is not 0.

Such as the code he has shown, or:

CRectangle Foo* = dynamic_cast<CRectangle*>( ppoly1 );
if ( Foo )
cout << Foo->area() << endl;

However... this puts the burden on checking on the derived class type to the
calling code. It is forseen that you may have rectangle, square, octogon,
hexagon, triangle, polygon, etc.. and it is not a good thing to have to
check for each differnet type.

But, consider, all polygons have an area. Even though each may be
calculated differently, each differnet polygon will probably have an area()
method. This being the case, it makes sense to put a pure virtual method
("virtual ...=0") in the base class. Then the calling code doesn't have to
care about what actual shape it is, only that it is a polygon. Simply
adding a method

int area() = 0;

to your base class will allow your code to compile and is the appropriate
OOP thing to do.
 
T

tony_in_da_uk

I am compiling the following code, main.cpp, as follows:
gcc main.cpp

I get the following compile error:
main.cpp: In function `int main()':
main.cpp:28:no matching function for call to`CPolygon::area()'

The code is listed below:

#include <iostream>
using namespace std;

class CPolygon {
public:
virtual void set_values (int a, int b) { width=a; height=b; };

protected:
int width, height;
};

class CRectangle: public CPolygon {
public:
int area () { return (width * height); };
};

int main ()
{
CPolygon * ppoly1 = new CRectangle;
ppoly1->set_values (4,5);
cout << ppoly1->area() << endl;
return 0;

}

Why does this not compile?

You have a pointer to the base class, which does not have a virtual
area function, so you can not call such a function through the
pointer. Having area in the actual derived class is not relevant -
the compiler only lets you access the known interface for a CPolygon
through such a pointer. You can add a virtual area function to
CPolygon to get the behaviour you want.

Tony
 
A

Axter

I am compiling the following code, main.cpp, as follows:
gcc main.cpp

I get the following compile error:
main.cpp: In function `int main()':
main.cpp:28: no matching function for call to `CPolygon::area()'

The code is listed below:

#include <iostream>
using namespace std;

class CPolygon {
public:
virtual void set_values (int a, int b) { width=a; height=b; };

protected:
int width, height;
};

class CRectangle: public CPolygon {
public:
int area () { return (width * height); };
};

int main ()
{
CPolygon * ppoly1 = new CRectangle;
ppoly1->set_values (4,5);
cout << ppoly1->area() << endl;
return 0;

}

Why does this not compile?

Because you're using a base class pointer, and the base class pointer
knows nothing about a function that is unique to the derived class.
Any function you access in the derived class through the base class
pointer has to be a virtual function declared in the base class.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,438
Messages
2,571,699
Members
48,796
Latest member
Greg L.
Top