I sort of understand how you defined them as static or virtual calls now.
- Derived::f1() is static because Base::f2() is static. However Derived::f2() hides that, so wouldnt that mean that Derived::f1() is going to call virtual Derived::f2() anyway, and should therefor be dynamic? I mean when its actually called Derived::f2() WILL hide Base::f2() so why is Derived::f1() considered static.
- Also how is d.f2() static? Derived::f2() is calling virtual Derived::f3() (and we arent going to care what is called past that, reason at bottom) so should it not be dynamic?
- And Derived::f3() is static because its calling virtual Base::f3().. which must be some rule that if you call Base explicitly its static, because otherwise I'd assume its dynamic.
So shouldnt whether its a static or dynamic call be declared by what it actually calls, not what it 'would-of' called? For example, what it actually calls:
Code:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f1()
{
cout << "Base::f1() -> ";
f2(); // static binding (as f2() is non-virtual)
}
void f2()
{
cout << "Base::f2() -> ";
f3(); // dynamic binding
}
virtual void f3()
{
cout << "Base::f3() " << endl;
}
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual void f1()
{
cout << "Derived::f1() -> ";
f2(); // static as f2() is not virtual, and thanks to the "hiding rule" Derived::f2() hides Base::f2()
}
virtual void f2()
{
cout << "Derived::f2() -> ";
f3(); // dynamic, as Base::f3() is virtual. If Derived did not override it, Base::f3() would be called
}
virtual void f3()
{
cout << "Derived::f3() -> ";
Base::f3(); // static: we're telling the compiler specifically to call Base::f3()
// if this was dynamic, this call would be infinitely recursive.
}
};
int main(int argc, char* argv[])
{
Derived d; // static
Base& b1 = d;
Derived& d1 = d;
cout << "Object 1, Function 1" << endl;
d.f1(); // static
cout << "\n\nObject 1, Function 2" << endl;
d.f2(); // static
cout << "\n\nObject 1, Function 3" << endl;
d.f3(); // static
cout << "\n\nObject 2, Function 1" << endl;
d1.f1(); // dynamic
cout << "\n\nObject 2, Function 2" << endl;
d1.f2(); // dynamic. If we have a Derived2, derived from Derived and that supplies an f2(), then Derived2::f2() will be called.
cout << "\n\nObject 2, Function 3" << endl;
d1.f3(); // dynamic
cout << "\n\nObject 3, Function 1" << endl;
b1.f1(); // dynamic
cout << "\n\nObject 3, Function 2" << endl;
b1.f2(); // static, as Base::f2() is non-virtual
cout << "\n\nObject 3, Function 3" << endl;
b1.f3(); // dynamic
cin.get();
}
Output:
Object 1, Function 1
Derived::f1() -> Derived::f2() -> Derived::f3() -> Base::f3()
Object 1, Function 2
Derived::f2() -> Derived::f3() -> Base::f3()
Object 1, Function 3
Derived::f3() -> Base::f3()
Object 2, Function 1
Derived::f1() -> Derived::f2() -> Derived::f3() -> Base::f3()
Object 2, Function 2
Derived::f2() -> Derived::f3() -> Base::f3()
Object 2, Function 3
Derived::f3() -> Base::f3()
Object 3, Function 1
Derived::f1() -> Derived::f2() -> Derived::f3() -> Base::f3()
Object 3, Function 2
Base::f2() -> Derived::f3() -> Base::f3()
Object 3, Function 3
Derived::f3() -> Base::f3()
Of course you cant decide if its virtual or static by what it ends up on, since it always will end up stopping on Base::f3(); in this example because it doesnt go anywhere, and therefor would make all of your calls static.
I'm "eternally confuzzled (tm)" and could be wrong, and it wouldnt be the first time, considering I've only ready up on virtual declarations in classes once.