Why might you define an abstract member funcion?

A

AnonMail2005

Here's the snippet you are referring to:

class Funct {
public:
virtual int doit(int x) = 0;
virtual ~Funct() = 0;
};

inline Funct::~Funct() { } // defined even though it's pure virtual;
it's faster this way; trust me

That comment is referring to the inline specifier of the function, NOT
the virtual specifier.

Base classes should have virtual destructors if you are going to
manipulate, and more specifically delete, instances of the class via a
base class pointer. If they do not have virtual destructors, the
results of the delete are undefined.

For the inline comment, virtual functions are usually ignored for
inlining. That's because the function being called is usually
determined at runtime, not at compile time. Destructors are different
since a base class destructor is called whenever a base class or any of
it's derived classes are destructed. The comment is saying for this
case, the inline specifier will actually be paid attention to.
 
A

Alipha

Pete said:
In this section of the FAQ:

http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10

an abstract destructor is given a definition with the cryptic comment
"It's faster this way, trust me". Why?

Is it faster to type? I notice that the derived classes in that example
seem mysteriously not to require a destructor.

Or somehow faster at runtime? What purpose is served by the destructor
being abstract?

Thanks.

To critique parashift's code, a destructor should generally not be pure
virtual, but simply virtual. By making it pure virtual, you're forcing
derived classes to provide a programmer-defined destructor
implemention, when many times, the compiler-supplied destructor is all
that's needed.

class Funct {
public:
virtual int doit(int x) = 0;
virtual ~Funct() {}
};

class Derived : public Funct {
public:
int doit(int x) { return x; }
// no ~Derived() is needed (unless Derived needs to do additional
cleanup)
};
 
J

Jay Nabonne

To critique parashift's code, a destructor should generally not be pure
virtual, but simply virtual. By making it pure virtual, you're forcing
derived classes to provide a programmer-defined destructor
implemention, when many times, the compiler-supplied destructor is all
that's needed.

This works fine for me:

class A
{
public:
virtual ~A() = 0;
virtual void MyFunc() {};
};

inline A::~A() {}

class B: public A
{
};

int main()
{
A* pA = new B;
return 0;
}

No need for the derived class to provide anything.

- Jay
 
P

Pete C

class Funct {
public:
virtual int doit(int x) = 0;
virtual ~Funct() = 0;
};

inline Funct::~Funct() { } // defined even though it's pure virtual;
it's faster this way; trust me


Base classes should have virtual destructors if you are going to
manipulate, and more specifically delete, instances of the class via a
base class pointer. If they do not have virtual destructors, the
results of the delete are undefined.

I know why we use virtual destructors. I was asking why this snippet
used a PURE virtual destructor. Especially since the derived classes
don't implement destructors of their own. Under the normal rules for
abstract functions this would not be allowed (at least, the derived
classes would still be abstract). Any idea why?
 
P

Pete C

To critique parashift's code, a destructor should generally not be pure
virtual, but simply virtual. By making it pure virtual, you're forcing
derived classes to provide a programmer-defined destructor
implemention

And yet they didn't provide one in that example. Do you think it was a
mistake on their part, or am I still missing something?

Thanks...
 
P

Pete C

I see what you mean. Maybe it's a sneaky way to make a class abstract
when you don't have any other pure virtual methods.
 
A

Alf P. Steinbach

* Pete C:
In this section of the FAQ:

http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10

an abstract destructor is given a definition with the cryptic comment
"It's faster this way, trust me". Why?

Is it faster to type?

Since the definition is provided 'inline' a compiler that doesn't do whole-
program optimization can easily optimize that particular destructor call
away in each derived class' destructor, thus, it's probably a little bit
faster than not inline. The destructor is there and is virtual because this
class is designed for polymorphic usage.

I notice that the derived classes in that example
seem mysteriously not to require a destructor.

Actually Funct2 and Funct3 do, and the compiler generates it, and the base
class is designed to support such derived classes.

Or somehow faster at runtime? What purpose is served by the destructor
being abstract?

Why it's pure virtual I don't know but it doesn't hurt. For a large class it
can be a time-saving convention to make the destructor pure virtual if the
class is abstract, so you only have to look at the destructor to ascertain
whether it is abstract or not. Essentially a convention that gives
at-a-glance effect of Java or C# 'abstract' keyword -- but I wouldn't rely
on such a convention, and I don't think it adds much useful information.

What baffles me is nothing of the above, but why Marshall has chosen to use
the term 'functionoid' instead of the well established (for C++) 'functor'.

However, Google helped me quickly find Marshall's own explanation of that
choice, at <url: http://www.kegel.com/dkftpbench/callbackDemo.html>:

<quote>
A functionoid is an
object that has one major method. It's basically the OO extension of a
C-like function such as printf(). One would use a functionoid whenever the
function has more than one entry point (i.e., more than one "method") and/or
needs to maintain state between calls in a thread-safe manner (the C-style
approach to maintaining state between calls is to add a local "static"
variable to the function, but that is horribly unsafe in a multi-threaded
environment).

A functor is a special case of a functionoid: it is a functionoid whose
method is the "function-call operator," operator()(). Since it overloads
the function-call operator, code can call its major method using the same
syntax they would for a function call. E.g., if "foo" is a functor, to call
the "operator()()" method on the "foo" object one would say "foo()". The
benefit of this is in templates, since then the template can have a template
parameter that will be used as a function, and this parameter can be either
the name of a function or a functor-object. There is a performance
advantage of it being a functor object since the "operator()()" method can
be inlined (whereas if you pass the address of a function it must,
necessarily, be non-inlined).
</quote>

Cheers,

- Alf
 
J

Jay Nabonne

I see what you mean. Maybe it's a sneaky way to make a class abstract
when you don't have any other pure virtual methods.

Exactly. It's about the only way to make a class abstract ("must be
derived from to use") when there is no existing pure virtual function,
without changing the class interface (e.g. making an existing virtual
function pure or adding a dummy pure virtual function, which is just plain
ugly).

- Jay
 

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

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top