0

I truly don't understand why this works like this.

#include<iostream>

using namespace std;
class Figura{
public:
int x;
int y;
virtual void pomak(int dx=10,int dy=1)
    {

        x+=dx;
        y+=dy;
        cout<<"Figura"<<endl;


    }
};
class Skakac:public Figura{
public:
void pomak(int dx=2,int dy=-1)
    {
        cout<<dx<<endl;
        x+=dx;
        y+=dy;
        cout<<"Skakac"<<endl;


    }
};

int main()
{
    Skakac S;
    S.x=0;
    S.y=0;
    Figura* x=&S;
    cout<<x->x<<" "<<x->y<<endl;
    x->pomak();
    cout<<S.x<<" "<<S.y<<endl;




 }

When i call function pomak() it couts dx as 10, although it calls second function pomak(not the virtual one) and i clearly stated that dx = 2.

2 Answers2

2

According to the standard (N4140):

8.3.6 Default arguments
...
10 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. [ Example:

struct A {
    virtual void f(int a = 7);
};
struct B : public A {
    void f(int a);
};
void m() {
    B* pb = new B;
    A* pa = pb;
    pa->f(); // OK, calls pa->B::f(7)
    pb->f(); // error: wrong number of arguments for B::f()
}

—end example ]

AlexD
  • 32,156
  • 3
  • 71
  • 65
  • How can i fix it? I want to have default values in both virtual and overriding functions – rusherzy thaman May 30 '16 at 19:14
  • Not sure if it is a good idea, but you can make a virtual function `getDefaults(int&dx. int&dy)` and override it as needed. – AlexD May 30 '16 at 19:16
  • What do you mean by that? Can you put in code for me – rusherzy thaman May 30 '16 at 19:21
  • `virtual void getDefaults(int&dx, int&dy) {dx=10;dy=-1;}`, then call it from `pomak`. But I am not sure at all if it is a good idea to change defaults in this case. – AlexD May 30 '16 at 19:24
  • BTW, it you have `virtual void getDefaults` or follow the recommendation of **@user2079303**, you may not need having `pomak(int,int)` as `virtual`. (Assuming that behavior of `pomak(int,int)` is the same, and virtuality is used in attempt to provide different defaults.) – AlexD May 30 '16 at 19:47
1

The function is called through a pointer to Figura. The default value for the argument is clearly 10.

Because the function is virtual, the most derived version of the function is used, based on the dynamic type of the pointed object, which is Skakac. The default arguments of the dynamic type are not used as the standard, already quoted by AlexD, states.

P.S.

it calls second function pomak(not the virtual one)

Skakac::pomak is also virtual.

How can i fix it?

If by "fix it" you mean "How can I override the default argument", then I recommend using overloading instead of default arguments:

class Figura {
    // ...
    virtual void pomak() {
        pomak(10, 1);
    }
    virtual void pomak(int dx, int dy) {
        // ...
    }
};
class Skakac: public Figura {
    // ...
    void pomak() {
        pomak(2, -1);
    }
    void pomak(int dx, int dy) {
        // ...
    }
};
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • How can i fix it? I want to have default values in both virtual and overriding functions – rusherzy thaman May 30 '16 at 19:15
  • @rusherzythaman see the edit. – eerorika May 30 '16 at 19:24
  • @user2079303 In that case, it could be quite confusing to have both `pomak()` and `pomak(int,int)` virtual... – AlexD May 30 '16 at 19:30
  • @AlexD well, `pomak()` must be virtual, in order to get the default values based on the dynamic type. And `pomak(int,int)` must be virtual because they have different behaviour. Although, if the outputs are for exposition only, then the intended behaviour would be the same and there would be no need to make it virtual. – eerorika May 30 '16 at 19:36
  • I tried this and it works. AlexD should i leave it like this? – rusherzy thaman May 30 '16 at 19:38