virtual functions

the question is if a virtual function in base has different parameters of the function with same name in derived
are they connected or not??

and if the marameters are the same and have different default values then what??
i have these questions about the following code..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Base {
    public:
        virtual void f( int ) {
            cout << "Base::f(int)" << endl;
        }

        virtual void f( double ) {
            cout << "Base::f(double)" << endl;
        }

        virtual void g( int i = 10 ) {
            cout << i << endl;
        }
    };

    class Derived: public Base {
    public:
        void f( complex<double> ) {
            cout << "Derived::f(complex)" << endl;
        }

        void g( int i = 20 ) {
            cout << "Derived::g() " << i << endl;
        }
    };

    void main() {
        Base    b;
        Derived d;
        Base*   pb = new Derived;

        b.f(1.0);
        d.f(1.0);
        pb->f(1.0);

        b.g();
        d.g();
        pb->g();

        delete pb;
    }


it prints

base f double
derived f complex
base f double
10
20
10
If a derived class defines a function with the same name as a function in the base class but with different parameters, then the derived function hides the base class version, this means that a derived class can never call the base class function.

If a virtual function is overloaded in a derived class with different default parameters, since default parameters are statically bound but virtual functions are dynamically bound, if you have a pointer to a base class object whose actual type is of derived, like this Base* b = new Derived; then the default parameter used will be that of Base, not derived. This is why you should not redefine default parameters when overloading an inherited function.
Last edited on
ok i understand this

and about different parameters(not default) in derived and base in a virtual function
doesnt it matter?
Sorry, quirkyusername's answer is not quite true. While the derived version does hide
the base version, the base can still be called, however you have to use scoping. Example:

1
2
3
4
5
6
7
8
9
10
11
class Base {
    virtual void foo( int x ) { }
};

class Derived {
    virtual void foo( double d ) { }

    void some_member_function() {
        Base::foo( 3.14 );
    }
};


And as for the second question, if your virtual method contains default parameters,
for the sake of sanity, ensure that overrides of the method in derived classes use
the same default value! The reason is that the answer depends upon what
declarations the compiler has seen and what the compiler knows about the object.

Consider this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

struct Base {
    virtual void foo( int x = 20 ) { std::cout << x << std::endl; }
};

struct Derived : Base {
    virtual void foo( int x = 10 ) { std::cout << x << std::endl; }
};

void frobnicate( Base& b ) {
    b.foo();
}

int main() {
    Derived d;
    d.foo();             // Outputs 10, as expected
    frobnicate( d );  // Outputs 20!!!
}


The same object outputs two different answers! Why? Because when the compiler
is compiling d.foo(); in main(), the compiler knows that d is an instance
of Derived, so it looks at Derived's declartaion of foo, as we'd expect, and assumes
that we wanted to implicitly pass 10 to foo().

But when the compiler is compiling b.foo(); in frobnicate(), the compiler
doesn't know the actual type of its parameter; it only knows that it is either a
Base or something derived from Base. So the only foo() it can look at is Base's,
so in this case it assumes we wanted to call foo() with 20 instead of 10.


jsmith wrote:
Sorry, quirkyusername's answer is not quite true. While the derived version does hide the base version, the base can still be called, however you have to use scoping.
Well, the visual C++ Compiler complains that it can't call a static member of Base

EDIT: I didn't test it for gcc but for visual C++ quirkyusername is true
Last edited on
that explained the thing at all
thank you very much both..
closed account (z05DSL3A)
As jsmith said, it just requires scoping to access hidden bases, consider this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
using namespace std;

class Base {
public:
    virtual void foo( int x ) 
    {
       cout << "Base::f(int)" << endl;
    }
};

class Derived: public Base  
{
public:
    virtual void foo( double d ) 
    {
        cout << "Derived::f(double)" << endl;
    }
    using Base::foo;
 
};

class Derived2: public Base  
{
public:
    virtual void foo( double d ) 
    {
        cout << "Derived2::f(double)" << endl;
    }
};

int main() 
{
    Base base;
    Derived derived;
    Derived2 derived2;

    base.foo(3);
    derived.foo(3);
    derived2.foo(3);

}
Base::f(int)
Base::f(int)
Derived2::f(double)
Last edited on
coder777: what version of Visual C++ are you using?

But there is a typo in my example above. I meant to call foo() with an integer,
not a double, since the base class version takes an int. Not sure if you copied
my example verbatim, but if you did, that might explain it.

closed account (z05DSL3A)
jsmith, Your Derived, in the first example, isn't.
I used that example:

1
2
3
4
5
6
7
8
9
10
11
class Base {
    virtual void foo( int x ) { }
};

class Derived {
    virtual void foo( double d ) { }

    void some_member_function() {
        Base::foo( 3.14 );
    }
};


Actually there are three typos:
1. Derived isn't derived from Base (that's the explanation)
2. Base::foo() is private
3. and least: 3.14 instead of 3

EDIT: Testing it with Base as the base class: you can call Base::foo()
Last edited on
ahh yes I forgot about that, cheers guys
Topic archived. No new replies allowed.