1

I am having two problem about virtual methods.

First:

class Parent
{
public:
    virtual void SHOW(int x = 5) { cout << "PARENT " << x << endl; }
};

class Child : public Parent
{
public:
    virtual void SHOW(int y = 10) { cout << "CHILD " << y << endl; }
};

int main()
{
    Child Y;

    Parent* P = &Y;
    P->SHOW();

    getch();  
    return 0;     
}

I think tt should be CHILD 10 but the result is CHILD 5

And another:

class Parent
{
public:
    virtual void SHOW() { cout << "PARENT" << endl; }
};

class Child : public Parent
{
private:
    virtual void SHOW() { cout << "CHILD" << endl; }
};

int main()
{
    Child Y;
    Parent* P = &Y;
    P->SHOW();

    getch();  
    return 0;     
}

It'll show CHILD on the screen. I don't know how a private method which was called from outside?

Thank you. I'm learning English so.. :)

dnvThai
  • 123
  • 8
  • 2
    possible duplicate of [virtual function default arguments behaviour](http://stackoverflow.com/questions/6464404/virtual-function-default-arguments-behaviour) – user1937198 Apr 06 '14 at 14:12
  • Default values are not inherited, even if the function is defined virtually. They are resolved to the default value of the *static* type of the variable (in this case, of the parent class). As to the question in the second to last paragraph about a private method, what do you mean? – gnometorule Apr 06 '14 at 14:16
  • CHILD's SHOW is a private method. Why it can be called from P->SHOW() – dnvThai Apr 06 '14 at 14:44

3 Answers3

2

1) C++ Standard says

A virtual function call (10.3) uses the default arguments in the declaration of the virtual function determined by the static type of the pointer or reference denoting the object. An overriding function in a derived class does not acquire default arguments from the function it overrides.

§8.3.6/10

2) Overriding public virtual functions with private functions in C++

Community
  • 1
  • 1
Mario Corchero
  • 5,257
  • 5
  • 33
  • 59
1

A virtual function call uses the default arguments in the declaration of the virtual function determined by the static type of the pointer you use to call the function. In your case the static type of P is Parent although the dynamic type resolves to Child. This is according to C++ standard.

Sammy
  • 356
  • 2
  • 7
1

This is a good example of why it is typically best to make virtual functions private and public functions non-virtual. Herb Sutter once called this the Non-Virtual Interface Idiom (NVI).

Let's apply it to your code. I'll also change the function name "SHOW" to "show", because all-uppercase in C++ usually denotes a macro. Furthermore, I'll add a virtual destructor, because newbies are reading these questions and they shouldn't see a polymorphic class without one. Note that destructors are an exception to NVI.

Here we go:

class Parent
{
public:
    void show(int x = 5) { doShow(x); }
    virtual ~Parent() {}
private:
    virtual void doShow(int x) { cout << "PARENT " << x << endl; }
};

class Child : public Parent
{
private:
    virtual void doShow(int x) { cout << "CHILD " << x << endl; }
};

Default arguments are usually useful for code which uses the objects of a class. That code then uses the public functions.

Parent *p = new Child;
p->show(); // here's where a default argument is a useful feature
delete p;

Inheriting classes, however, are interested in something completely different, namely in the virtual functions of the base class. It turns out that you rarely feel the need for default arguments when you write the code for a subclass.

Bottom line:

  1. Default arguments and virtual functions shouldn't be mixed. There is an item for this in the famous Effective C++ book by Scott Meyers: "Never redefine an inherited default parameter value". You should read that book.
  2. Using NVI, you will typically not have this problem anyway, because it turns out default arguments are more of a thing for public functions, and with NVI, public functions aren't virtual.
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • While this is certainly an very elegant solution to this issue, I disagree with you that NVI should be used everywhere. There are certainly situations where its usage is useful and produces cleaner/safer code, but generaly saying that one must not declare public virtual methods is wrong IMO – Sebastian Hoffmann Apr 06 '14 at 14:48
  • I'm not saying you should use it everywhere. But I am saying that it should be the default. – Christian Hackl Apr 06 '14 at 14:58