Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!rutgers!bellcore!faline!thumper!ulysses!andante!alice!shopiro From: shopiro@alice.UUCP (Jonathan Shopiro) Newsgroups: comp.lang.c++ Subject: Re: Functions not defined in base class Summary: Use ``pure virtual'' functions Message-ID: <9300@alice.UUCP> Date: 4 May 89 15:18:14 GMT References: <897@servax0.ESSEX.AC.UK> Organization: AT&T Bell Laboratories, Murray Hill NJ Lines: 104 In article <897@servax0.ESSEX.AC.UK>, goss@ese.essex.ac.uk (Gossain Sanjiv (5N.7.10)) writes: [slightly edited] > I have a particular application where I am representing a group > of related classes by an abstract class. Now, I require that > a function is passed an instance of > one of these classes as a parameter in one of its methods. > I would like to be able to declare the abstract class as the > type in the function declaration, as I won't know until > run time, which class of my group it will be. Are you > confused? Let me explain with some code... > > I would like a function to have the decl: > > void f(abstractClass* anInstanceOfAbsClass) > > now, anInstanceOfAbsClass could be any instance of a sub-class > of abstractClass. > > f should be able to call a member function of anInstanceOfAbsClass > that is not defined for abstractClass, should I > There are (approximately) two cases: 1) There is some function that will be implemented in every derived class, but it has different implementations in each. This is exactly what virtual functions were invented for. Here's how: class abstractClass { // ... public: virtual void function() = 0; // a ``pure virtual'' function }; The initializer is new syntax with 2.0. It has several effects: 1) you don't need an implementation for the base class 2) you must redeclare it in each derived class (possibly also as pure virtual) 3) you can only create objects of the derived classes If you call the function directly or indirectly in the constructor of the base class, something bad will happen, but as soon as the base class constructor completes, all will be well. 2) There is some function that is only appropriate for some of the derived classes. This case is more problematical. What you should look at is how you might decide to call the function. Perhaps the function is a sub- operation of some function that is defined for all the derived classes. Then you can just put it in the classes where it is appropriate. class Base { // ... public: virtual void function() = 0; }; class Derived : public Base { public: void function(); void special(); }; void Derived::function() { // ... special(); // ... } Here ``function'' will be defined in all derived classes, and ``special'' is not defined in all derived classes. This is the most natural way to use C++, and you should try to structure your programs in this way. I am sure you will like the result. If this is not possible, you have two choices. First, you can put the special function in only the class where it is appropriate and then use a cast to call it. Using the declarations above, you could write void f(Base* bp) { // decide that bp really points to a Derived object, and you // want to call special ((Derived*)bp)->special(); } This is guaranteed to work only if bp really does point to a Derived object. If the special function will be defined in several derived classes, but not all, you can create an intermediate class, derived from Base, which has special as a pure virtual function, and then derived the classes which will implement special from that. There is no performance penalty for extra classes in a derivation hierarchy. The other choice is to put special in the Base class, as a virtual function whose implementation calls some error routine, and to override it in the appropriate derived classes. The advantage of this approach is that you get to define the behavior in case of error, and the advantage of the other approach is that each class has only appropriate member functions. Personally I prefer the first approach, with casting. -- Jonathan Shopiro AT&T Bell Laboratories, Warren, NJ 07060-0908 research!shopiro (201) 580-4229