[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: What happened to the NcFile destructor?



Hi Tom,

> 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 ?

Oops, I thought people were only using the derived concrete classes
NcNewFile and NcOldFile, which both have public destructors.  I made this
change because of the appended note I got in January about a problem with
the way I had been making NcFile an abstract base class.  I accepted his
suggested solution uncritically, because the compilers didn't squawk when I
tried it, and all my tests still worked.  Now it appears that I'll have to
look more carefully at the HP-UX problem that caused this ...

> 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 have an NcFile, it looks like
this is a problem.  Thanks for pointing this out.

Incidentally, I'm thinking that the idea of having NcOldFile and NcNewFile
derived from the abstract base class NcFile was actually a case of
poorly-designed inheritance that needs to be corrected in release 2.4.  I
think this can be fixed up in a backward compatible way (as suggested by Dan
Schmitt) with a few macros in netcdf.hh, something like:

#define NcOldFile NcFile
#define NcNewFile NcFile
#define Clobber New
#define NoClobber Write

with new class-specific enum:

    enum FileMode {
        ReadOnly = NC_NOWRITE,
        Write = NC_NOCLOBBER,
        New = NC_CLOBBER
      };

and then just doing everything with NcFiles.  Do you have any opinions about
or see any problems with this approach?

--Russ


Subject: C++ interface
To: address@hidden
Date: Tue, 31 Jan 1995 14:33:41 +0000 (GMT)
From: "Tomas Johannesson" <address@hidden>
X-Mailer: ELM [version 2.4 PL23]
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Content-Length: 4179      

Dear Russ,

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., virkar ekki
    // 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.

best wishes, tomas