> if a class has virtual functions, is it better to make the destructor
virtual
Absolutely. Consider the following:
class base
{
public:
base() {}
~base() {}
};
class derived : public base
{
some_big_class* p;
public:
derived() { p = new some_big_class(); }
~derived() { delete p; }
};
main()
{
base* myobj = new derived();
// ...
delete myobj;
}
The destructor will never be called, and your program will leave blobs
of garbage behind it. If you make the destructor virtual, the 'delete
p;' line will be called and your memory leak will be fixed. (You can
convince yourself of this by adding a line of output in derived's
constructor.)
if B is a subclass of A, can an array of A's be used in the place of
an array of B
This is asking if the following.
Since B derives from A, an object of type B can be used any place an
object of type A is expected, e.g.:
void foo(A* somearg);
// ...
B someobj;
foo(&someobj);
This is okay. But should an object of type B[] be substituted for a
type A[]? So should the following work?
void foo(A somearg[]);
// ...
B somearray[100];
foo(somearry);
My understanding (and Victor's answer) is no. From an implementation
perspective, the sizes of A and B are different. Thus when foo looks
for somearg[1], it won't be where it thinks it is because that will be
the end of somearray[0]. Graphically:
| somearg[0] | somearg[1] | .... | somearg[n-1]
| somearray[0] | somearray[1] | ... |
somearray[n-1]
More theoretically, imagine somearg[] as a collection of base objects.
Thus foo should be able to add something to that collection (and could
if the program was using vectors or another containter class instead of
arays). But foo thinks they are base objects, so adds a new base
object. But now somearray[], which is supposed to be a collection of
derived objects, now isn't because it has a base object in it! Oops!
Despite what I said before, the following code compiles and crashes at
runtime under VS.Net 7. Is this correct behavior on the part of the
compiler?
int gid;
class base
{
int id;
public:
virtual int ID() { return id; }
base() { id = gid++; }
virtual ~base() {}
};
class derived : public base
{
int did;
public:
int ID() { return did; }
derived() {base(); did = 1000;}
~derived() { }
};
void foo(base a[])
{
for(int i = 0 ; i<100 ; ++i)
cout << a[i].ID() << endl;
}
int main()
{
derived d[100];
foo(d);
}