How do I implement final in C++

M

Medi Montaseri

Hi,

I think my problem is indeed "how to implement something like java's
final in C++"

The long version....

I have an abstract base class which is inherited by several concrete
classes.
I have a group of methods that I'd like to implement in the base class
and would like
to mandate that the client should send those messages directly to the
base class
(and not thru its derived classes). I guess that is similar to "final"
in Java...

How do I enforce such policies...

Thanks
 
P

Phlip

Medi said:
I think my problem is indeed "how to implement something like java's
final in C++"

The long version....

I have an abstract base class which is inherited by several concrete
classes.
I have a group of methods that I'd like to implement in the base class
and would like
to mandate that the client should send those messages directly to the
base class
(and not thru its derived classes). I guess that is similar to "final"
in Java...

How do I enforce such policies...

Read /Effective C++/, then do these three things:

- not write 'virtual' on the methods
- write a sternly worded comment
- write no other methods in the heirarchy with the same name

In C++, you don't pay for what you don't use. Not writing 'virtual' states
you do not intend to use a slot in the secret vtable (or whatever) for this
function, so you won't pay for it.

You need the last item because if you had two functions with the same name,
they would hide each other. Pointers, references or instances to one type
would bind that message at compile time to to one method, and pointers,
references or instances to another type would bind to another method. So if
you change the pointer or reference type, but not the ultimate instance, you
could silently change which type the compiler selects. Write more
defensively, to decrease the odds of a mistake like that: Don't give
different things the same name (unless they are, in fact, virtual overrides
of each other).

The cost of a real "final" in a strictly compiled language like C++ would be
too high.
 
M

Marc Schellens

Medi said:
Hi,

I think my problem is indeed "how to implement something like java's
final in C++"

The long version....

I have an abstract base class which is inherited by several concrete
classes.
I have a group of methods that I'd like to implement in the base class
and would like
to mandate that the client should send those messages directly to the
base class
(and not thru its derived classes). I guess that is similar to "final"
in Java...

How do I enforce such policies...

Thanks

Youi can call the baseclass method expicitely:

class b
{
virtual void method() {}
};

class d1: public b
{
void method();
};

class d2: public d1
{
void method();
};

int main( int argc, char* argv[])
{
d2 var;
var.b::method(); // calls b's 'method' function
}

hdh,
marc
 
M

Marcelo Pinto

Hi,

I think my problem is indeed "how to implement something like java's
final in C++"

The long version....

I have an abstract base class which is inherited by several concrete
classes.
I have a group of methods that I'd like to implement in the base class
and would like
to mandate that the client should send those messages directly to the
base class
(and not thru its derived classes). I guess that is similar to "final"
in Java...

How do I enforce such policies...

Thanks

Adding to the OP's question:
_____
| c1 | virtual void a() = 0;
|_____| vritual void b() = 0;
^
___|___
__|__ __|__
implements b | c2 | | c3 | both implements a
virtual void b();|_____| |_____| virtual void a();
^
___|____
__|__ __|__
| c4 | | c5 | NOT supposed to REimplement a
|_____| |_____| both implement b

If I have the situation shown above, is there a way to prevent the
implementers of classes derived from c3 (c4 and c5 in the diagram) to
accidentally reimplement method a? By a way I mean a compiler error
like the one I suppose is shown in Java when one tries to reimplement
a method declared as final.

Thanks

Marcelo Pinto
 
M

Marcelo Pinto

Karl Heinz Buchegger said:
The question is: Why would you want to do this?
Suppose I derive a class d6 from c5 and I absolutely need to reimplement
a(), because the one in c3 doesn't fit my needs. What should I do then?

In that situation you should derive from c1, not from c3.

Best regards,

Marcelo Pinto.
 
A

Alf P. Steinbach

Marc Schellens said:
Medi said:
Hi,

I think my problem is indeed "how to implement something like java's
final in C++"

The long version....

I have an abstract base class which is inherited by several concrete
classes.
I have a group of methods that I'd like to implement in the base class
and would like
to mandate that the client should send those messages directly to the
base class
(and not thru its derived classes). I guess that is similar to "final"
in Java...

How do I enforce such policies...

Thanks

Youi can call the baseclass method expicitely:

class b
{
virtual void method() {}
};

class d1: public b
{
void method();
};

class d2: public d1
{
void method();
};

int main( int argc, char* argv[])
{
d2 var;
var.b::method(); // calls b's 'method' function
}

hdh,
marc

Thanks Marc...but I'm looking for a more defensive approach.....you
are showing
an honor system by which the client is sending a message to the right
class/object.

I'm looking for a way to enforce that no other derived classes can
inherit this given
method of base class.

Ugh. If a derived class does not _inherit_ a method, then that method
does not exist in the derived class; that property is not what you
want unless your requirements list is a dynamic one created on the fly
to be non-implementable. A Java 'final' method is of course inherited.

The key property of a Java 'final' method is that it cannot be
overridden by a derived class.

In C++ the nearest technical feature is a non-virtual method. A non-
virtual C++ method can not be overridden (like a Java 'final' method),
and it is inherited (like a Java 'final' method). In short, it's what
you want.

Perhaps your confusion stems from the fact that a derived class can
redefine the method:


* Do you understand the difference between redefine (a non-virtual
method) and override (a virtual method)?


Now, on another tack, more in support of the view that C++ is lacking
in this respect.

The main difference between a non-virtual and a final method, which
you haven't said anything about as a requirement, is that in C++
this method cannot be virtual in base classes of the class where it's
defined. Where you want to _introduce_ 'finality' on a method in an
inheritance chanin you have, in C++, no technical feature that directly
supports that. In that case you have to use C++ to implement the
feature if you want it enforced at compile time, e.g. usign containment
instead of inheritance.
 
K

Karl Heinz Buchegger

Medi said:
That is a valid concern, if a given implementation does not fit the
need,
a derived class should be able to override (hide) the one implemented
in base.

However in my original posting, I was looking for a way to say

message foo() can only be send to Abstract_Bass_Class (eg
AbstractBase->foo())
and message foo() can not be send to any Derived_Classes....as in

But the question is: Do you really, really, really know that nobody
in the future will never want to do this and handle foo() on it's own.

You are not a magician and I am not. It often happens and it will
happen in the future, that someone might want to extend a class by
deriving from it in a way that you never thought of.
 
M

Mike Smith

Medi said:
from programming.
That is if the interface calls for certain functionality, it is
desirable for the tools (ie
programming languages) to accommodate the designer to set forth rules
and policies and
not to be at the mercy of notes, comments, honor systems and such....

Then you need a language other than C++. Other languages do more to
"help" prevent the programmer from screwing up, but the philosophy of
C++ is to give the programmer as much latitude and as many options as
possible, even if it increases the likelihood of making a mistake.
 
A

Alf P. Steinbach

Perhaps I should explain what I want to achieve and ask for the way in
C++.

That is a _very_ good idea.


I want to implement an interface (an abstract base class). I
also want this interface to maintain a container (a list of
ptr to objects of its derived classes). I'll also implement
a factory method in the base that produces instances of
its derived classes. eg

Employee->getNewEmployee().
Employee->listEmployees()

Technically that would be

Employee::getNew()
Employee::list()

Since I can not instantiate the abstract base, I figured I'll
implement a private static _employeeList as in
static map < string &, Employee *> _employeeList ;
Where getNewEmployee() factory method will populate.
OK.



But if I do something like

Employee *emp;
Employee *Bob = emp->getNewEmployee("Bob");

Technically this would be

Employee* Bob = Employee::getNew( "Bob" );


emp->listEmployees(); // I want this to work
Employee::list()



Bob->listEmployees(); // I don't want to allow this, as instance
Bob does not have access
// to the static data member.

(1)
In C++ an instance does have access to static members of its class.

(2)
Why on Earth do you _really_ want to disallow this?

(3)
If you really want or need to it's easily done by moving the factory
and the list out of the Employee class. Some possibilites are

* Free-standing functions.

* Separate class EmployeeFactory.

* Nested class Employee::Factory.


And that is why I was looking for a way to mandate that listEmployee()
message should only
be send to the interface and not any derived classes (or their
instances).

That isn't 100% meaningful; but see above.
 
M

Mike Wahler

Medi Montaseri said:
"Phlip" <[email protected]> wrote in message

Thanks for the reply....

Your suggestion 1 is granted, ie the method will not be a virtual
method in the base class.
Your suggestion 2 is also granted, but this is too week. I'm trying to
stop the programmer
who is about to inherit from base to even move a finger, ie stop
him/her at compile time.
Writing comments and honor systems only goes so far...
Your guesstion 3 is too restricted, I can not controll what some
derived class author
would like to call his/her method. If base implements foo() as a
concrete
method, then if a derived class implements a similar name method (ie
foo() again),
the client of derived object will get derived::foo() which is ok...I
just don't want the
client to send a message to a derived object and the call get routed
to the base.
One reason is what if I have a private static data member in my base
abstract class
and I don't want any derived objects inheriting my foo(), which then
the call would
fail as the derived object would not have access to the base private
data member.

I think the idea behind an abstract base class is to seperate design
from programming.
That is if the interface calls for certain functionality, it is
desirable for the tools (ie
programming languages) to accommodate the designer to set forth rules
and policies and
not to be at the mercy of notes, comments, honor systems and such....

Then I think you need a more 'hand-holding' language.
C++ (and C) is like a gun in a holster on your belt.
It's *your* responsibility to make sure it points where
it should before pulling the trigger. Ever hear the
phrase 'shoot yourself in the foot'? :)

-Mike
 
M

Marcelo Pinto

Karl Heinz Buchegger said:
And thereby reimplementing all the usefull functionality in c3 :)

As a matter of fact no. Because the functionality you wanted to
specialize is exactly the one was specialized by c3. Thus there is not
an usefull functionality in c3 for your new class.

And the question remains. Is there a way to prevent users of this
hierarchy from reimplement method a below class c3 other than with a
comment?

Thanks,

Marcelo Pinto
 
K

Karl Heinz Buchegger

Marcelo said:
As a matter of fact no. Because the functionality you wanted to
specialize is exactly the one was specialized by c3. Thus there is not
an usefull functionality in c3 for your new class.

Granted. Not in this example. But add a function c() to c3 and the situation
changes ... I then want a class d6, derived from c5, with all the functionality
of c5 and c3 and yet have a special handling of a().

And the question remains. Is there a way to prevent users of this
hierarchy from reimplement method a below class c3 other than with a
comment?

No. For exactly this reason: You never know what another programmer
might want to do with your code.

As it turned out (as usual), the OP was heading to a design error without
recognizing it, tried to invent or use a feature which is not in the language
to overcome a problem he will not have if his design is correct.
 
C

chan

Hi,

I think my problem is indeed "how to implement something like java's
final in C++"

The long version....

I have an abstract base class which is inherited by several concrete
classes.
I have a group of methods that I'd like to implement in the base class
and would like
to mandate that the client should send those messages directly to the
base class
(and not thru its derived classes). I guess that is similar to "final"
in Java...

How do I enforce such policies...

Thanks

The answer lies, in essence, with the friend operator and the way C++
constructs virtually derived objects. Consider the following:

template <typename T>
class DerivationLock
{
friend T;

private:
// This can only be called by this class or a friend!
DerivationLock() {};
}

class FinalClass : virtual public DerivationLock<FinalClass>
{
...
}



Now we can merrily create an instance of FinalClass as it is a friend
of the base and so can call its private constructor. But see what
happens when we try and derive from FinalClass:

class Usurper : public FinalClass
{
...
}

The constructor of Usurper will try and call the private constructor
for DerivationLock directly, without going through the construction of
FinalClass (this is what virtual inheritance does). Obviously, this
is not allowed by the compiler as Usurper is not a friend of
DerivationLock (note that friendship is not inherited). Hence we
can't derive from FinalClass.

Hope that addresses your problem.
 
E

emerth

Write Java not C++.

Or write C not C++ or Java. Then you can just give the victims a library.

But you still can't stop 'em writing their own code that uses a C library.


Hi,

I think my problem is indeed "how to implement something like java's

etc etc etc
 

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

No members online now.

Forum statistics

Threads
474,139
Messages
2,570,805
Members
47,351
Latest member
LolaD32479

Latest Threads

Top