1

I have a question regarding to the C++ virtual function.

The derived class (DerivedAlgo) implements the virtual function (BaseAlgo::process) but changes a little bit in the function signature by using the DerivedData type as the input parameter instead of BaseData.

Despite the pure abstract function in the base class, I am still able to create an instance of the DerivedAlgo class and the compiler does not complain at all.

I just wonder anyone knows any C++ rule which can explain the following code.

class BaseData{}; class DerivedData: public BaseData{}; class BaseAlgo{ public: virtual void process(BaseData& data) = 0; }; class DerivedAlgo: BaseAlgo{ public: virtual void process(DerivedData& data){ std::cout << "hello world!" << std::endl; } }; 

In my another sample code, I define process(DerivedData&) and process(BaseData&).

The compiler can still run through without complaining any ambiguity.

class DerivedAlgo{ public: virtual void process(DerivedData& data){...} virtual void process(BaseData& data){...} }; BaseData baseData; DerivedData derivedData; derivedAlgo.process(baseData); derivedAlgo.process(derivedData); 

I really appreciate any of your inputs. Thanks!

4
  • Do you mean to use private inheritance? Commented Apr 18, 2011 at 18:12
  • Did you actually instantiate the instance of DerivedAlgo in your first test? The compiler won't complain unless you try to make one... Commented Apr 18, 2011 at 18:25
  • Also, this might be compiler-specific, so you should add the compiler/version info. Commented Apr 18, 2011 at 18:25
  • @user713885: That's funny. I would really update my compiler (and probably OS) if I were you. Your compiler has been released 5 years ago. Commented Apr 18, 2011 at 19:26

3 Answers 3

1

Your first example doesn't compile on g++ 4.2. For reference I did this:

#include <iostream> class BaseData{}; class DerivedData: public BaseData{}; class BaseAlgo{ public: virtual void process(BaseData& data) = 0; }; class DerivedAlgo: BaseAlgo{ public: virtual void process(DerivedData& data){ std::cout << "hello world!" << std::endl; } }; int main() { DerivedAlgo da; return 0; } 

And got this:

error: cannot declare variable 'da' to be of abstract type 'DerivedAlgo' note: because the following virtual functions are pure within 'DerivedAlgo' note: virtual void BaseAlgo::process(BaseData&) 

If something like my example did compile then you almost surely have a buggy compiler.

Your second example will compile because it overrides the abstract function. The first call will call the base data version while the second call will call the derived version of process.

Note that in your first example you're hiding the process(base) version of the function, not overriding it at all. You shouldn't change the function signature when overriding virtual functions.

Sign up to request clarification or add additional context in comments.

3 Comments

From my understanding, I also guess my sample code may not work due to the pure abstract. It compiles in my platform. This is quite interesting to me so I ask the question.
Sorry. I forget to add my platform information: gcc version 3.4.6 and Red-hat linux 2.6.9-89 64-bit.
@user713885: So what you're saying is that you have a really old compiler, and it compiles code it shouldn't, and which modern versions don't. That says more about gcc 3.4.6 than anything else.
1

Are you sure you're not getting a compiler error?

When I compile this (in MSVC9):

#include <cstdlib> #include <memory> #include <iostream> class BaseData{}; class DerivedData: public BaseData{}; class BaseAlgo{ public: virtual void process(BaseData& data) = 0; }; class DerivedAlgo: BaseAlgo{ public: virtual void process(DerivedData& data){ data; std::cout << "hello world!" << std::endl; } }; int main() { DerivedAlgo da; } 

I get the expected error:

1>.\main.cpp(21) : error C2259: 'DerivedAlgo' : cannot instantiate abstract class 1> due to following members: 1> 'void BaseAlgo::process(BaseData &)' : is abstract 1> .\main.cpp(9) : see declaration of 'BaseAlgo::process' 

This is because you cannot override virtuals with different parameter lists:

10.3 Virtual Functions

2/ If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides97) Base::vf.

The only leeway you have in declaring overrides in the derived class is with covariant return types.

It's possible your compiler didn't thoroughly check your code if you never actually call the derived class.

2 Comments

I do create an instance of the DerivedAlgo just like what I do in the second example. My compiler goes through. My platform is gcc 3.4.6 RHEL 2.6.9-89.
@user: Geez. Where did you get that compiler? The Smithsonian?
0

the problem you have is that c++ does not support double dispatch. You need to use a Visitor pattern on your BaseAlgo class.

1 Comment

Cool! Thank for bringing this up. I read it long ago but almost forgot. It is really useful. I am using gcc 3.4.6 and it can compile the above code. From the other responses, seems like the code cannot compile at all in MSVC and gcc 4.2 due to the pure abstract.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.