views:

301

answers:

4

Let's say we have

class A {    
public:    
    virtual int foo() { cout << "foo!"; }    
}

class B : public A {
public:    
    virtual int foo() =0;
}

class C : public B {
public:
    virtual int foo() { cout << "moo!"; }
}

Is this really overriding? I think this is actually overloading. What is the meaning of making something like this, design-wise?

We got a base class A. Then we got an abstract derived class B which is derived from the concrete class A, and then a realization of B via C.

What are we doing here and does it make any sense?

+1  A: 

It seems to me that the only effect of the pure virtual method here is to make B an abstract class.

Paul Mitchell
+1  A: 

It's still overriding, because when you have a pointer p of type A* to instance of class C, p->foo() still calls C::foo()

Probably, the designer wanted to insert an abstract class in the hierarchy deriving from some concrete class, and force overriding of the method in subclasses. I don't think it's terribly wise.

jpalecek
+3  A: 

Overloading would mean that you had two functions of the same name but with different parameters. That's not the case here.

Example:

int functionA() { /*...*/ };
int functionA(int someParameter) { /*...*/ };

Overriding means rewriting a function with the same parameters in a subclass. That is what you presented as an example.

That's the definition part. Now on to the design:

When you have a pure virtual function, concrete subclasses have to override it. So by adding a pure virtual function, you ensure that all subclasses provide the same set of functions (=interface). This seems to be the case in the sample code.

But it is not a very good example, as the concrete superclass already implements a default functionality for foo(). When there is an abstract subclass that redefines it to be purely virtual, it is a sign for me that the class hierarchy is flawed because a subclass (and the callers of foo()) usually should be able to fall back to the default implementation. It's a bit hard to explain with such an abstract example, but a hierarchy like this is a bit suspicious to my eye.

Sebastian Dietz
Yes, it looks "suspicious" but I wouldn't say it's a flaw in itself, maybe in the real-world code it made sense. And by the way, +1 since you're the only one answering the overloading/overriding part :)
Paolo Tedesco
@orsogufo: You are right, it's hard to determine if the concrete/abstract/concrete hierarchy is a flaw or a feature. With "suspicious" I meant that I would take a good look at it in case it needed some refactoring work when I would stumble over that sort of code :-)
Sebastian Dietz
+1  A: 

You're saying that classes deriving from B must implement int foo();. You might want to do something like this to force other programmers to think about how they want foo() to behave, but I think it's a bad idea - in reality they're likely to implement by calling A::foo().

If you just want to make B abstract, give it a pure virtual destructor - you'll also need to provide an implementation of the destructor to avoid link error though.

Joe Gauterin