C++ interface

T

The Directive

Is there a way in C++ to create a "true" interface. I want to create
an absract class that other classes can inherit from and be forced to
implement the interface's abstract (pure virtual) methods. However, it
has to be a true interface in that it doesn't add any overhead (when
the derived object is created) with the interface's constructors and
destructor because they don't exist for the interface. Does that make
sense? I just want an interface, not all the OOP stuff like
constructors, destructor and etc. In other words, I don't want the
interface's (system default or user defined) constructors & destructor
to be called.
 
J

Jeff Schwab

The said:
Is there a way in C++ to create a "true" interface. I want to create
an absract class that other classes can inherit from and be forced to
implement the interface's abstract (pure virtual) methods. However, it
has to be a true interface in that it doesn't add any overhead (when
the derived object is created) with the interface's constructors and
destructor because they don't exist for the interface. Does that make
sense? I just want an interface, not all the OOP stuff like
constructors, destructor and etc. In other words, I don't want the
interface's (system default or user defined) constructors & destructor
to be called.


Determine what operations you want to be available as part of this
interface. Implement those operations for all types that must support
the interface. If some code needs to be able to work with anything that
supports the interface, put the code in a template.

template< typename T >
void do_stuff( T const& t )
{
// T supports interface I, which means it's
// ok to perform operations x, y, and z on t.

t.x( );
t.y( );
z( x );
}

This approach is often called "generic programming," although I believe
mathematicians call it "formalism." For a great example of a practical
application of this technique, look at the STL iterators, algorithms and
containers.

-Jef
 
R

Ron Natalie

The Directive said:
I just want an interface, not all the OOP stuff like
constructors, destructor and etc. In other words, I don't want the
interface's (system default or user defined) constructors & destructor
to be called.

Sorry, you get the OOP stuff whether you want it or not. However,
C++ is very efficient about not wasting time on things that are not used.
If your class has no data members or base classes and no user defined
constructor, then I've never seen a compiler that generates any code
on construction or destruction.

Hence a C++ interface is just a class that has:

No non-static data members.
Pure virtual methods for the interface routines.
No base classes that aren't themselves interfaces.
 
E

E. Robert Tisdale

The said:
Is there a way in C++ to create a "true" interface. I want to create
an absract class that other classes can inherit from and be forced to
implement the interface's abstract (pure virtual) methods. However, it
has to be a true interface in that it doesn't add any overhead (when
the derived object is created) with the interface's constructors and
destructor because they don't exist for the interface. Does that make
sense? I just want an interface, not all the OOP stuff like
constructors, destructor and etc. In other words, I don't want the
interface's (system default or user defined) constructors & destructor
to be called.

A good optimizing C++ compiler should not add any overhead.
Can you show us an example where your C++ compiler adds such overhead?
 
C

Cy Edmunds

The Directive said:
Is there a way in C++ to create a "true" interface. I want to create
an absract class that other classes can inherit from and be forced to
implement the interface's abstract (pure virtual) methods. However, it
has to be a true interface in that it doesn't add any overhead (when
the derived object is created) with the interface's constructors and
destructor because they don't exist for the interface. Does that make
sense? I just want an interface, not all the OOP stuff like
constructors, destructor and etc. In other words, I don't want the
interface's (system default or user defined) constructors & destructor
to be called.

Here is an example from the uvs library:

class IDiDist // discrete statistical distribution
{
public:
virtual double
mean() const = 0;

virtual double
variance() const = 0;

// other pure virtual functions omitted for brevity

virtual
~IDiDist() {}
};

Characteristics of this type of interface:

1) no data
2) no constructor
3) no methods except pure virtual ones
4) a do-nothing virtual destructor

I know you said you wanted no destructor, but it is really sort of required
for this type of application. Otherwise there are circumstances in which a
destructor in a derived class might not get called resulting in a resource
leak. If you can somehow be sure no derived class will have a destructor
(but how?) then you could in principle leave the virtual destructor out.

I generally avoid deriving one interface from another. That's not a hard and
fast rule but seems to work out better. Having a class implement multiple
interfaces in parallel is of course fine.
 
R

Ron Natalie

Cy Edmunds said:
I know you said you wanted no destructor, but it is really sort of required
for this type of application.

It's only required if you call delete on an interface class pointer. Probably
better to make the destructor protected (and not virtual).
 
C

Cy Edmunds

Ron Natalie said:
It's only required if you call delete on an interface class pointer. Probably
better to make the destructor protected (and not virtual).

Sure, but when you write a class like this how are you supposed to know how
derived classes are going to be used? Not including a virtual destructor in
an interface class is unsound IMHO.
 
R

Ron Natalie

Cy Edmunds said:
Sure, but when you write a class like this how are you supposed to know how
derived classes are going to be used? Not including a virtual destructor in
an interface class is unsound IMHO.

It's not UNSOUND. It doesn't make a fleas ass difference whether
the interface is derived from or not (and since the class is full of pure
virtual functions it's almost a certain).

By making the destructor PROTECTED as I stated, there's no way to
destroy the class through the interface pointer, which would be the only
time that the destructor would need to be virtual. It was my argument
that it's probably a bad idea to allow people to do this:

Interface* ip = GetMeSomeThingThatSupportsInterface();
delete ip;

Making the destructor protected prevents the above. Making it
virtual does not.
 
C

Cy Edmunds

Ron Natalie said:
It's not UNSOUND. It doesn't make a fleas ass difference whether
the interface is derived from or not (and since the class is full of pure
virtual functions it's almost a certain).

By making the destructor PROTECTED as I stated, there's no way to
destroy the class through the interface pointer, which would be the only
time that the destructor would need to be virtual. It was my argument
that it's probably a bad idea to allow people to do this:

Interface* ip = GetMeSomeThingThatSupportsInterface();
delete ip;

Making the destructor protected prevents the above. Making it
virtual does not.

I don't understand your example. If GetMeSomeThingThatSupportsInterface uses
operator new() to create an instance of something derived from Interface
then how does it get deleted? I can't delete it myself without dynamic
casting to a type which has a destructor.

I disagree that deleting an object polymorphically is a bad idea. In fact
making the destructor protected prevents me from using it with smart
pointers.
 
R

Ron Natalie

Cy Edmunds said:
I don't understand your example. If GetMeSomeThingThatSupportsInterface uses
operator new() to create an instance of something derived from Interface
then how does it get deleted?

Through some interface call or some external scheme. An example is the Microsoft
COM objects. The IUnkown interface provides reference counting that manages
when the object actually needs to committ suicide. You don't delete stuff through
interfaces in general.
I can't delete it myself without dynamic casting to a type which has a destructor.

Nothing can prevent people being stupid with dynamic cast.
I disagree that deleting an object polymorphically is a bad idea. In fact
making the destructor protected prevents me from using it with smart
pointers.

Nothing precludes that, and it defeats the interface paradigm if you actually
think the interface IS the object. The interface is just a set of manipulations
of the object. Not all interfaces are BASE CLASSES. Some are mixins.
 
C

Cy Edmunds

Ron Natalie said:
Through some interface call or some external scheme. An example is the Microsoft
COM objects. The IUnkown interface provides reference counting that manages
when the object actually needs to committ suicide. You don't delete stuff through
interfaces in general.

Actually, I DO delete things through interfaces! There is an advantage to
it. For instance with COM there is a reference counting mechanism built into
every COM object as you say. But a reference counted smart pointer abstracts
a similar mechanism and keeps it separate from the object itself. This
allows me to write a whole library of polymorphic objects without even
considering reference counting or memory management. All I need to do is
provide a do-nothing virtual destructor in all interfaces.
destructor.

Nothing can prevent people being stupid with dynamic cast.


Nothing precludes that,

Nothing precludes what? A reference counted smart pointer deletes the object
through the pointer when the smart pointer is destroyed. Hence if the object
cannot be deleted this way the code will not compile.
and it defeats the interface paradigm if you actually
think the interface IS the object. The interface is just a set of manipulations
of the object. Not all interfaces are BASE CLASSES. Some are mixins.

An interface with a virtual destructor can be used as a base class or added
later as a "mixin". For instance, in

http://home.rochester.rr.com/cyhome/uvs/samp.html

uvs::IDiDist (an interface to a discrete distribution) is used as a base
class for various discrete distributions but is added to uvs::DiSummary
("mixed in") at the point where we define histogram uvs::DiHistogram. That
just models the fact that a histogram is a distribution and a sample
statistic both.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top