Sign in to follow this  

C++ Theory: Polymorphism & Abstract Classes & Heterogenous Arrays - Confirm

This topic is 3493 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Finishing up learning C++ and the ideas behind it and I'm hoping that a few people would read over what I've learned concerning C++ design concerning Polymorphism, Heterogenous Arrays, and Abstract Arrays and answer a few questions. Major questions I've bolded to make it clear my main concerns. note, a few times below i refer to 'baseclass' and 'abstractclass' they're the same thing for what I refer to, the type the heterogenous array is based off of I'll draw my questions from the following small sample program. Note it doesn't have an abstract class but I have a few questions refering to them. Main.cpp
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#include "BaseClass.h"
#include "DerivedClass.h"

DerivedClass test;

int main(void)
{
	BaseClass * temp[10];

	temp[1] = &DerivedClass();
	//temp[1]->base_id = 0;

	cout << temp[1]->derived_id; // out of scope of abstract class

	delete temp[1];
	int input;

	cout << "\nChecking for memory leaks: Check output!\nType an int to exit! ";
    cin >> input;
	return 0;
}

BaseClass.h & .cpp
class BaseClass
{
public:
	//constructor
	BaseClass();
	//vars
	int base_id;
};

// FILE BREAK

#include "BaseClass.h"

BaseClass::BaseClass()
{
	base_id = 1;
}

DynamicClass
#include "BaseClass.h"

class DerivedClass : public BaseClass
{
public:
	//constructor
	DerivedClass();
	//vars
	int derived_id;
};

// FILE BREAK

#include "DerivedClass.h"

DerivedClass::DerivedClass()
{
	derived_id = 2;
}

This is my understanding of the topic: A homogeneous array is an array consisting of elements of the same class. A Heterogenous array is an array consisting of classes derived from the Base class. BaseClass * temp[10]; // a Heterogenous array able to // point to BaseClass or DerivedClass elements & functions able to be referenced are those defined in the BaseClass class only. Functions and elements defined in DerivedClass only work inside the object and are not able to be referenced, outside of a call from a BaseClass inherited/overloaded function. For this reason, abstract classes are often used as a base class used to define the total possible function/element list of any derived object that could be possibly made. Heirarchys can be made from here on out with derived classes, however, all referencable functions/elements are defined in the Abstract class. When a Heterogenous array is called, it generates a list of base class pointers. This base class is often an abstract class that provides the footprint for referencable material. Questions: Memory allocation: 1)when "heterogenousarray[index] = new derivedClass" is called, memory for a complete abstract class plus any extra elements of the derived class are set asside, even if the derived class does not use elements of the abstract class. 2)How do virtual declarations in the abstract class affect memory allocation for derived classes that don't overload any of the virtual functions. 3)When a new derived element is declared in a heterogenous array, it sets asside memory for the total abstract class, wether or not the derived function will use those variables/functions, in addition to anything above the defined class not covered in abstract class. 4)Do derived classes automatically 'trim the fat' and not allocate memory for abstract virtual functions/elements they don't use? 'virtual' declaration 1)is 'virtual' anything else than a notation that the function should be overwriten by a derived class. 2)Are 'virtual' functions, by design, supposed to be overwritten by every derived class? And thus they should never be 'optional' functions for any derived class? 3)Is there a virtual version for elements such as int, float ect? reference 1)Dynamic classes can have elements not definded by an abstract class, however these are not directly referencable outside the class, likewise functions not defined in the abstract class can not be called outside the object. Is there any way to reference a variable/element not defined in the base/abstract class outside of the class? design 1)If you have a derived class with a (compile time)large array you wish to reference outside the class, the abstract class will also have to have the same array. Will this create waste for other derived classes that don't use the array since it has to be in t he abstract class, and memory will have to be set asside for it?

Share this post


Link to post
Share on other sites
Ugh, I won't go over every statement, since there's lots of confusing stuff in there, but instead will show how polymorphism works:

Imagine an invisible base class that every polymorphic class extends:

struct VTable {
int n;
void *members;
};
struct PolymorphicObject {
VTable vtable;
}


Now let's say we declare a polymorphic class (the following casts might not compile):


class Base : public PolymorphicObject {

void foo() { // virtual function

// polymorphic function signature
typedef void (*foo_pointer)();

// this function is stored at index 0 of vtable
// cast it to proper signature
foo_pointer fp = (foo_pointer)this->members[0];

// call it
fp();
}

void baz( int x ) { // also virtual
// polymorphic function signature
typedef void (*baz_pointer)(int);

// this function is stored at index 1 of vtable
// cast it to proper signature
baz_pointer fp = (baz_pointer)this->members[1];

// call it
fp(x);
}
}


So....

Every polymorphic class has a VTable member. This table is created by compiler.

When you call a function, it dereferences the vtable pointer and finds the appropriate method (at given index). It then calls that.

VTables are static, function code is static.

The memory footprint of any polymorphic class will be at least size of pointer to vtable.


Also:
-
delete temp[1];
You just deleted something you didn't allocate. That will crash at best, or do weird things.

- Your derived classes don't implement virtual destructor. Classes that will be used for polymorphism, or which are intended for extension should provide virtual destructor, to force the compiler to treat them as polymorphic (vtable and all that).

- 'Abstract Arrays'&'Heterogenous Arrays' - I'm not really sure why this terminology. In C++, an array is typed. The fact that you can store pointers to polymorphic objects doesn't change the nature of array.

Base * array[100] is an array of pointers to Base. These pointers may be derived classes as well, but that doesn't change the array in any way.

Quote:
1)is 'virtual' anything else than a notation that the function should be overwriten by a derived class.
It's an indication that it *may* be replaced, rather than shadowed.

Quote:
2)Are 'virtual' functions, by design, supposed to be overwritten by every derived class? And thus they should never be 'optional' functions for any derived class?
Option.
Quote:
3)Is there a virtual version for elements such as int, float ect?
No - those are data types. Functions are different, and not even first-class objects in C++.

Quote:
Memory allocation:
This is a big bowl of fish in C++, especially when it comes to inheritance. Books can be written about this, and it's impossible to explain all of it in a quick post.

All arrays of pointers have same allocated length (n * sizeof(void*)). Exception to this may be function pointers. The actual length depends on alignment and compiler.

Quote:
Is there any way to reference a variable/element not defined in the base/abstract class outside of the class?
Sure:
((derived*)array[1]).derived_id;
or
dynamic_cast<derived*>(array[1]).derived_id;

If you need to do this, it's a good indication of poor design. In general, polymorphism protects from implementation specifics. If you need to specialize, it's usually an ugly sign.

Quote:
1)If you have a derived class with a (compile time)large array you wish to reference outside the class, the abstract class will also have to have the same array. Will this create waste for other derived classes that don't use the array since it has to be in t he abstract class, and memory will have to be set asside for it?


This depends solely on where and how you allocate the instances of these class.

Share this post


Link to post
Share on other sites
Your understanding of inheritance is the wrong way round. You don't stuff everything you might ever need into the base class interface. You start with a base class interface which defines operations for X and then you inherit from that interface if you are an X. For example the Shape base class defines members representing properties and operations common to all shapes. Square is-a Shape and therefore inherits from Shape. Everywhere you can use a Shape you can use a Square. Circle also is-a Shape. Circle might define a radius property, but Shape would not, since not all shapes have a radius.

Also, if you ever see a C++ book or tutorial which mentions these headers:

#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>


Run a mile. Said book or tutorial is ten years out of date. The correct headers are:

#include <cstdlib>
#include <cstdio>
#include <iostream>


Σnigma

Share this post


Link to post
Share on other sites
Thx, I'll review this.

The code example was abit loose for what I was trying to get at, (and left the delete statement in there from testing) but the replies clear up some stuff. I'll do more testing.

Share this post


Link to post
Share on other sites

This topic is 3493 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this