Shao Zhang wrote in in
comp.lang.c++:
Hi,
I am not sure if the virtual keyword for the derived classes are
required given
that the base class already declares it virtual.
class A
{
public:
virtual ~A();
}
class B : public A
{
public:
virtual ~B();
}
class C: public B
{
public:
virtual ~C();
}
My question is whether I need the virtual keyword for class B and C? If
I don't need it, is it recommanded to always add the virtual keyword?
Does it have any negative effect at all?
Contary to other posters in this thread, you should only use
virtual if its a requirment, i.e. is the virtualness of the member
is part of the derived classes interface.
With the example above 'A' has a virtual destructor, this means
that 'A' is a type that can (as a pointer) hold deletable
references to instances of type 'A' or any type derived from it.
Presumably this is a requirment for type 'A'. If it isn't then
virtual shouldn't be there in the first place.
If type 'B' doesn't share this requirment then 'B' shouldn't
impose it.
C++ doesn't make you pay for things you don't use, as a programmer
you shouldn't make youself (or others) pay for things you don't use.
As an example:
#include <iostream>
#include <ostream>
#include <list>
struct base
{
virtual ~base() {}
};
struct container
{
private:
typedef std::list< base * > base_list_t;
std::list< base * > base_list;
public:
~container()
{
base_list_t::iterator
ptr = base_list.begin(),
lim = base_list.end()
;
for (; ptr != lim; ++ptr )
{
delete *ptr;
}
}
void add( base *bp )
{
try
{
base_list.push_back( bp );
}
catch ( ... )
{
delete bp;
throw;
}
}
};
struct derived : base
{
~derived()
{
std::cout << "~derived()\n";
}
};
int main()
{
container c;
c.add( new derived() );
c.add( new derived() );
}
Now refactor using boost::shared_ptr:
http://www.boost.org/libs/smart_ptr/smart_ptr.htm
#include <iostream>
#include <ostream>
#include <list>
#include "boost/shared_ptr.hpp"
struct base
{
};
struct container
{
private:
typedef std::list< base * > base_list_t;
std::list< boost::shared_ptr< base > > base_list;
public:
template < typename T >
void add( T *bp )
{
base_list.push_back( boost::shared_ptr< base >( bp ) );
}
};
struct derived : base
{
~derived()
{
std::cout << "~derived()\n";
}
};
int main()
{
container c;
c.add( new derived() );
c.add( new derived() );
}
In both of the examples 'derived' /inherits/ from 'base' the ability
to be placed (via new) in an instance of 'container'. How 'base' and
'container' meet this requirment is none of the 'derived' types
business.
Rob.