24

I am just testing with virtual keyword and inheritance concepts in c++. I have written a small program:

#include<stdio.h>
#include<iostream>

using namespace std;

class cna_MO
{
  public:
    virtual void print()
    {
        cout << "cna_MO" << endl;
    }
};

class cna_bsc:public cna_MO
{
  public:
    void print()
    {
        cna_MO::print();
    }

    void print(int a)
    {
        cout << "cna_BSC" << endl;
    }
};

class cna_Mo
{
    cna_MO *_mo;

  public:
    cna_Mo()
    {
        _mo = new cna_bsc;
    }

    virtual void print(int a)
    {
        cout << "cna_Mo with arg" << endl;
        _mo->print(5);
    }

    virtual void print()
    {
        cout << "cna_Mo" << endl;
        _mo->print();
    }
};

int main()
{
    cna_Mo valid_mo;
    cout << "old case is started" << endl;
    valid_mo.print();
    cout << "new case is started" << endl;
    valid_mo.print(5);
    return 0;
}

What I have done here is I have overloaded a virtual function in parent class in child class! Is this not the right thing to do?

I am getting the compilation errors as below:

"temp10.cc", line 45: Error: Too many arguments in call to "cna_MO::print()".

Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
Vijay
  • 65,327
  • 90
  • 227
  • 319
  • 2
    If you really need `stdio` (it is not needed in the code you gave), [you should include `cstdio` rather than `stdio.h`](http://stackoverflow.com/questions/301586/what-is-the-difference-between-using-includefilename-and-includefilename-h). – Luc Touraille Jan 11 '12 at 09:52
  • Also, you never delete the pointer you allocate in the cna_Mo constructor. – Mr Lister Jan 11 '12 at 10:15

6 Answers6

33

Once you overload a function from Base class in Derived class all functions with the same name in the Base class get hidden in Derived class.

Once you added the function cna_bsc::print(int a) to your derived class the function cna_MO::::print() is no longer visible to users of the Derived class. This is known as function hiding.

Solution: In order to make the hidden function visible in derived class, You need to add:

using cna_MO::print;

in the public section of your derived class cna_bsc.

Good Read:

What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • I got your point but still i have one more issue...edited the question.Please check the question now.even after doing the changes i am getting too many agrs error. – Vijay Jan 11 '12 at 09:38
  • 4
    The error is in `cna_MO::print()` when you call `_mo->print(5);` note that `_mo` is of the type `cna_MO *` and `cna_MO` class has no `print()` function which takes an single argument and hence the error. The reason for your confusion is usnig confusing non distinct class names, **DO NOT EVER USE NAMING CONVENTION LIKE THAT** – Alok Save Jan 11 '12 at 09:49
0

It's because the print function in the child class takes a parameter and the original doesn't.

in cna_MO (parent class):

virtual void print()

in cna_bsc (child class):

void print(int a)

Basically the child's print should not take an int argument:

void print()

EDIT:

Maybe the best would be to make passing the int optional ?

eg:

in cna_MO (parent class):

virtual void print(int a=-1) {
    if (a == -1) {
        // Do something for default param
    } else {
        cout << a;
    }
}

in cna_bsc (child class):

void print(int a=-1)

so if a == -1 you can probably assume, they didn't pass anything.

The trick is that both the parent and child need the same method siganture, meaning same return type and the same argument types.

matiu
  • 7,469
  • 4
  • 44
  • 48
  • Now it's because you're trying to call it passing an int on that line: `valid_mo.print(5);` – matiu Jan 11 '12 at 09:56
0

When you have a function with same name and different parameters in the derived class as that of the base class, then that function will be hidden. You can find more info here..

You can call the specific hidden function by calling like Base::hiddenFun();

liaK
  • 11,422
  • 11
  • 48
  • 73
0

That can't work because given a cna_MO *, you can see at compile-time that the pointed object does not (necessarily) have the int overload. If it actually pointed to a base-class object, _mo->print(5); would really have nothing to call. Also there can be an infinite number of (not yet implemented) derived classes that don't have to support this call.

  1. Every derived class must have print(int) - declare it in the base class.

  2. Every derived class need not have print(int) - cna_Mo only works with cna_bsc, so the member should be cna_bsc* _mo.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
visitor
  • 1,781
  • 10
  • 7
0

Ideally your print that takes an int should have a different name but given you want both functions to be called print, you should make them both non-virtual and make them call protected virtual functions.

class cna_MO 
{   
    public:     
     void print() { doPrint(); }

    protected:
     virtual void doPrint()
      {         cout << "cna_MO" << endl;     
      } 
};  


class cna_bsc:public cna_MO 
{   
    protected:     
       virtual void doPrint()  
                  // although with implementation no need to override it
       {         
            cna_MO::print();     
       } 

    public:
     void print(int a)    
      {
          doPrintInt( a );
      }

    protected:
      virtual void doPrintInt( int )
      {
        cout << "cna_BSC" << endl;     
      } 
 };  
CashCow
  • 30,981
  • 5
  • 61
  • 92
0

If you REALLY MUST do it like this, i.e. have a pointer to one class and initialise as a derived class, there's no choice but to always cast the pointer to the correct type when using it. In this case, ((cna_bsc*)_mo)->print(5);

Mr Lister
  • 45,515
  • 15
  • 108
  • 150