Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Virtual functions 1

Status
Not open for further replies.

CodingNovice

Programmer
Dec 30, 2003
108
GB
On the whole I understand virtual functions but there is one thing I cant fathom....

virtuality.h

#include <iostream>
using std::cout;
using std::endl;

class A
{
public:
virtual ~A() {}
virtual void f() { cout << &quot;A::f()&quot; << endl; }
};

class B : public A
{
public:
virtual ~B() {}
virtual void f() { cout << &quot;B::f()&quot; << endl; }
};

class C : public B
{
public:
virtual ~C() {}
virtual void f() { cout << &quot;C::f()&quot; << endl; }
};

class D : public C
{
public:
virtual ~D() {}
virtual void f() { cout << &quot;D::f()&quot; << endl; }
};

virtuality.cpp

#include &quot;virtuality.h&quot;

int main()
{
A* array[4] = { new C, new B, new A, new D };
B* array2[3] = { new B, new D, new C };
for( int i=0;i<4;++i)
{
array->f();
delete array;
}
for ( int i=0;i<3;++i)
{
(*array2).f();
delete array2;
}
std::cin.get();
return 0;
}

Now here in the first loop I call a virtual function through a pointer so dispatch is virtual. In the second loop I call a virtual function through an object. So shouldn't the second loop call B::f() 3 times? However it doesnt. It seems that that also is virtually dispatched. Thinking in c++ (my text book) says that virtual functions called through objects are early bound. So why does my second loop late bind?
I would like to be 100% sure in my head that when I use virtual functions I know exactly which function will be called. My compiler is telling me that im wrong here but i dont understand why.

I have an array with 3 B* in it that point to various derivatives of B. Surely when I dereference a B*, to get an object, I should get a B no matter what the dynamic type of the object really is. So calling f() through an object of type B should call B::f(). So why is this not happening? Where am I going wrong in my understanding?
 
I think I can answer the last part of your question but I would have to look at binding to answer the rest. The way you have your classes set up you inherit the previous class. When you write the functions over again...as you have with f.. you will always call the declared class not the inherited class. If you were to change the function name to fx say in class C and call f then it will dive to the last class inherited to get the f function. Otherwise you will have to direct the object to where you want it to pull from with &quot;newC->B::f();&quot;. Try this basic code out and play with it from there and you should get the hang of it pretty quick.

# include <iostream>
using namespace std;


class A
{
public:
virtual ~A() {}
virtual void f() { cout << &quot;A::f()&quot; << endl; }
};

class B : public A
{
public:
virtual ~B() {}
virtual void f() { cout << &quot;B::f()&quot; << endl; }
};

class C : public B
{
public:
virtual ~C() {}
virtual void f() { cout << &quot;C::f()&quot; << endl; }
};

class D : public C
{
public:
virtual ~D() {}
virtual void f() { cout << &quot;D::f()&quot; << endl; }
};

class E : public D
{
public:
virtual ~E() {}
virtual void fx() { cout << &quot;E::fx()&quot; << endl; }
};



void main()
{
A* newA = new A;
B* newB = new B;
C* newC = new C;
D* newD = new D;
E* newE = new E;

newA->f();
newB->f();
newC->f();
newD->f();

cout << &quot;E functions&quot; << endl;
newE->fx();
newE->f();
newE->A::f();
newE->B::f();
newE->C::f();
newE->D::f();

}

Hope this helped some!

CF

An expert is someone who learns more and more about less and less and eventually knows everything about nothing
 
well im thinking that the problem is this....

(*array2).f()

is not a call through an object as i first thought but instead must be a call through a reference to an object. That would explain the virtual dispatch when I thought that i would get static dispatch.Is this right? does the * in this case return me a B& rather than a B. Had it given me a B then B::f() would have been called. If the * returns a reference then virtual dispatch is assured by the language.
 
CodingNovice, you are right (in principle;) in your 2nd post. Indeed, in C++ no diff between call via ptr or ref and via object. See C++ Standard (there are no bold in the original):

The function called in a member function call is normally selected according to the static type of the object expression (clause 10), but if that function is
Code:
virtual
and is not specified using a qualified-id then the function actually called will be the final overrider (10.3) of the selected function in the dynamic type of the object expression Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression.

A virtuality is total. In any case C++ invokes 'true' object virtual function if you don't explicitly specify the point in a class tree (with ::). It's a simple and a logical rule.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top