Tom Glaess <tgl@xxxxxxxxxxxxxxxxx> writes:
> In netcdf 2.3.2 patch 4 (C++ interface), the destructor for NcFile has been
> made protected: (code from netcdf.hh)
>
> (parts of NcFile class deleted for brevity)
>
> protected:
>
> // Protected destructor used to make this an abstract base class.
> virtual ~NcFile( void );
...
> This makes deleting an NcFile object impossible from any outside application.
> I have never seen a protected destructor before. Why was this done? It is
> quite possible that I'm missing something, so if I am, please tell me.
>
> Also, the comment just above the destructor definition does not seem to make
> sense. Unless I'm wrong, if you want to make an abstract base class, wouldn't
> it need to be virtual ~NcFile( void )=0 ?
I incorrectly assumed that users would only use the concrete derived classes
NcNewFile and NcOldFile, which both have public destructors. This change
was included in patch 4 because of a note (excerpts of which are appended)
about a problem on HP-UX platforms with the previous way NcFile was
specified as an abstract base class. I incorporated the suggested change,
because our C++ compilers didn't complain, and our C++ interface tests still
worked. Now it appears that we need to look more carefully at the original
HP-UX problem.
> If I'm wrong about all of this, please tell me how I can delete a
> NcOld/NewFile. I'm at a loss.
You can explicitly invoke the destructor for an NcOldFile or NcNewFile,
since their destructors are public. If you only have an NcFile, you can't
delete it, so a work-around would be to make the virtual destructor public
again. Thanks for pointing out this problem.
I think that deriving NcOldFile and NcNewFile from the abstract base class
NcFile may be an over-zealous use of inheritance. This could be
fixed up in a backward-compatible way (as suggested by Dan Schmitt, thanks
Dan!) with a few macros in netcdf.hh:
#define NcOldFile NcFile
#define NcNewFile NcFile
#define Clobber New
#define NoClobber Write
and a new NcFile-specific enum:
enum FileMode {
ReadOnly = NC_NOWRITE,
Write = NC_NOCLOBBER,
New = NC_CLOBBER
};
and then just doing everything with NcFiles.
If anyone sees any problems with this approach, please let me know.
______________________________________________________________________________
Russ Rew UCAR Unidata Program
russ@xxxxxxxxxxxxxxxx http://www.unidata.ucar.edu
Subject: C++ interface
To: russ@xxxxxxxxxxxxxxxx
Date: Tue, 31 Jan 1995 14:33:41 +0000 (GMT)
...
I see that someone is working on the C++ interface.
I will therefore use this opportunity to
make the following minor suggestion for improvement.
The netcdf.hh file defines
a pure virtual destructor in order to define an abstract base class:
// Pure destructor used to make this an abstract base class.
virtual ~NcFile( void ) = 0;
My compiler (HP-CC) does not like this and complains about an
unsatisfied symbol because it apparently believes that pure
virtual destructors are not allowed (I think my compiler is
correct in this matter, a pure destructor is not allowed to
exist while the destructor is always supposed to be executed
when the base of the object is destroyed even in the case where
nothing except the basic destruction of builtin variables is done).
Anyway, in order to illustrate the problem the following simple program
*********************************
class XX {
public:
virtual ~XX()=0;
};
class YY {
public:
virtual ~YY() {;}
};
main()
{
YY y;
return 0;
}
*********************************
leads to the following error message on my platform (HP9000/720):
CC: "simple.cc", line 1: warning: please provide an out-of-line definition:
XX::~XX() {}; which is needed by derived classes (245)
/bin/ld: Unsatisfied symbols:
XX::~XX(void) (code)
*** Error code 1
I use the following workaround in netcdf.hh
***********************************
protected:
// a protected destructor makes a class an abstract base class
virtual ~NcFile( void );
public:
// Pure destructor used to make this an abstract base class. ...
// virtual ~NcFile( void ) = 0;
...
************************
I suggest that you specify the virtual base class by making the destructor
or equivalently a dummy constructor protected. This has the same effect,
but is not illegal. Protected constructors and/or destructors prevent
the definition of objects except through their own children
which is what you want to achieve.
...