views:

232

answers:

7
#include <iostream>
using namespace std;

class Duck {
public:
        virtual void quack() = 0;
};

class BigDuck : public Duck {
public:
  //  void quack();   (uncommenting will make it compile)

};

void BigDuck::quack(){ cout << "BigDuckDuck::Quack\n"; }

int main() {
        BigDuck b;
        Duck *d = &b;
        d->quack();

}

Consider this code, the code doesn't compiles. However when I declare the virtual function in the subclass, then it compiles fine.

The compiler already has the signature of the function which the subclass will override, then why a redeclaration is required?

Any insights.

+2  A: 

The definition of Quack() in your base class is "abstract" - it has no implementation. This tells the compiler that your derived class must implement it. Failure to do so is a compilation error.

GalacticCowboy
But surely the compiler knows to expect it in the implementation. What purpose does the extract declaration serve?
Matt Ellen
@Matt Ellen: See my answer
the_drow
@Matt The language standard says it is required - this hs nothing to do with abstract classes, all virtual functions (and indeed all functions) work that way.
anon
It's been several years since I did anything with C++ "in anger", but I'm pretty sure that the code is not actually providing an implementation for quack() but instead is either being ignored (since the compiler doesn't expect a method implementation) or implementing a new method (hiding/overload rather than override).
GalacticCowboy
@Galactic It is providing an implementation in the derived class. It certainly isn't being ignored!
anon
Duh - I withdraw my statement. :) I meant the way he had it written, but of course it wouldn't compile so neither part of my statement is correct. If it won't compile, it's not being ignored *or* overloading.
GalacticCowboy
+2  A: 

BigDuck could be another abstract class and you might not want to implement quack until you get to the base class ReallyBigDuck.

Pace
Now that's a good argument for being able to _not_ declare `quack`. But what's the argument for _having_ to declare it?
xtofl
+1  A: 

Until you provide an implementation, ll classes that inherit from a class that contains PVF are abstract - they cannot be instantiated. In order to provide an such an implementation, you must declare the function in the class.

anon
+1  A: 

Declaring the methods in each classes will tell the compiler that class provides the different implementation for the method.

Also, in case you want to create the objects of BigDuck on stack then how will compiler should know the signature of quack().

BigDuck aDuck;
aDuck.quack();
aJ
+6  A: 

The redeclaration is needed because:

  • The standard says so.
  • It makes the compiler's work easier by not climbing up the hierarchy to check if such function exists.
  • You might want to declare it lower in the hierarchy.
  • In order to instantiate the class the compiler must know that this object is concrete.
the_drow
Thanks! That makes sense.
Matt Ellen
@Matt Ellen: No problem
the_drow
The = 0; at the end of the declaration means you HAVE to define it in the derived class. Not that you might want to.
Ben Burnett
@Ben: You might decide that you don't want to instantiate that class in a specific project :) But you are correct.What I meant that instead of implementing it one level below in the hierarchy you might want to implement it **even lower**
the_drow
+2  A: 

Because C++ separates 'declaration' from 'polymorphism': any function needs a declaration for the compiler, regardless if it's virtual or not.

Your example doesn't go far enough, it has the 'abstract class' problem: a BigDuck cannot be instantiated because it has no implementation of quack in it's interface.

Generalizing the problem, we can declare the base function not pure virtual:

class Duck { public: virtual void quack(){} };

class BigDuck : public Duck {}; 
void BigDuck::quack(){ cout << "QUACK!"; }//overrides, but doesn't declare

In here, the compiler will complain that it has a symbol BigDuck::quack that wasn't declared. This has nothing to do with abstract classes or anything.

(Note: gcc says: error: no 'void BigDuck::q()' member function declared in class 'BigDuck' )

xtofl
+5  A: 

If you change:

virtual void quack() = 0;

to

virtual void quack();

It will compile without implementing quack() in HugeDuck.

the = 0; at the end of the function declaration is essentially saying that all BigDucks will quack, but that it has to be implemented by each derived duck. By removing the = 0; the BigDuck quack will get called unless you implement quack in HugeDuck.

EDIT: To clarify the = 0; is saying that the derived class will have the definition for the function. In your example it is expecting HugeDuck to define quack(), but as you have it commented it out it does not.

As a side note, since all ducks can quack perhaps your original Duck class that we can not see should implement quack() instead?

Ben Burnett