Pointers to virtual vs. non-virtual member functions

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 1035 Views - Last Post: 05 September 2013 - 12:25 PM Rate Topic: -----

#1 JSolnit  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 04-September 13

Pointers to virtual vs. non-virtual member functions

Posted 04 September 2013 - 11:09 AM

Hello, this is my first post to the C and C++ forum.

I have been asked by a potential employer to become an expert on all things relating to virtual functions and one specific aspect I was asked to look into was the difference between pointers to virtual and non-virtual member functions.

The information I've found thus far has been very light on explanation of the distinction. I know there's a size difference in memory, but I'm looking for a good explanation of what is different about the implementation of the two pointer types and why the pointer to a virtual member function requires more space.

Thanks for any insight you can provide.

Is This A Good Question/Topic? 0
  • +

Replies To: Pointers to virtual vs. non-virtual member functions

#2 jimblumberg  Icon User is online

  • member icon

Reputation: 5447
  • View blog
  • Posts: 16,971
  • Joined: 25-December 09

Re: Pointers to virtual vs. non-virtual member functions

Posted 04 September 2013 - 11:28 AM

Show a small sample of some code to illustrate your question.

Jim
Was This Post Helpful? 0
  • +
  • -

#3 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 6111
  • View blog
  • Posts: 21,035
  • Joined: 05-May 12

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 05:29 AM

Quote

I have been asked by a potential employer ...


Sounds like an interview question...
Was This Post Helpful? 0
  • +
  • -

#4 JSolnit  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 04-September 13

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 05:39 AM

View PostSkydiver, on 05 September 2013 - 05:29 AM, said:

Sounds like an interview question...



Indeed it is. Albeit an informal one and one which this interviewer even encouraged me to "go check some forums" on. He admitted to not yet knowing the answer himself and was curious to see what I could discover. If I violated some forum guideline by posting in this manner I apologize.

View Postjimblumberg, on 04 September 2013 - 11:28 AM, said:

Show a small sample of some code to illustrate your question.

Jim



Thanks Jim, and if I were asking a more specific question I ordinarily would. I haven't even tried approaching this broad topic with any actual code and was just looking for an explanation or hint.
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 6111
  • View blog
  • Posts: 21,035
  • Joined: 05-May 12

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 05:47 AM

Apply the scientific method. Try some code and first prove or disprove the hypothesis that a pointer to a virtual function is larger than a pointer to a static function.

IMHO, the hypothesis is incorrect when dealing with modern 32-bit and 64-bit C compilers. A pointer is a pointer is a pointer. The pointer size to a virtual function is the same pointer size to static function. It was only the 16-bit and 8-bit compilers that made the distinction between a pointer and a long pointer.
Was This Post Helpful? 0
  • +
  • -

#6 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2579
  • View blog
  • Posts: 4,114
  • Joined: 21-June 11

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 08:16 AM

View PostJSolnit, on 04 September 2013 - 08:09 PM, said:

I was asked to look into was the difference between pointers to virtual and non-virtual member functions.


There is no difference. Pointers to virtual and non-virtual member functions have the same type, which means they also have to have the same size. Just consider the fact that a (non-template) function, which takes a member function pointer as an argument can be called with pointers to both virtual and non-virtual member functions as the argument. If the physical representation of such pointers would be different, that would not be possible.

There is however a difference between member function pointers and non-member function pointers, as you're probably already aware. The most obvious difference is of course that a member function pointer needs a receiver to be called and consequently uses a different syntax than regular function pointers. Another difference is that member function pointers do tend to be larger than regular function pointers (regardless of whether the pointed-to function is virtual or not). The reason for this size difference is that a member function pointer could be virtual and correctly looking up the right function to call requires some (obviously implementation-specific) book keeping, of whose exact nature I'm not exactly sure.


View PostSkydiver, on 05 September 2013 - 02:47 PM, said:

Apply the scientific method. Try some code and first prove or disprove the hypothesis that a pointer to a virtual function is larger than a pointer to a static function.


(I assume you meant "non-virtual" there instead of "static").

The problem with that is that JSolnit thought he already knew this to be the case, so he didn't think he'd need to test it. He just wanted to know why and testing wouldn't tell him that.

Also, as an aside, the problem with applying the scientific method to languages like C++ is that there's a lot of undefined and/or implementation-specific behavior. So experimentation might teach you more about your implementation than about the language in general. And in the case of undefined behavior it might lead you to dangerously wrong conclusions even on the same implementation. For example one might easily conclude based on experiments that signed integer overflow will cause wrap-around on gcc. Relying on that conclusion would eventually blow up in one's face though.

Quote

IMHO, the hypothesis is incorrect when dealing with modern 32-bit and 64-bit C compilers.


It is, but not for the reason you think.

Quote

A pointer is a pointer is a pointer.


Except a pointer to a member function is not just a pointer - they may store more than just the address of the function.

Quote

[ The pointer size to a virtual function is the same pointer size to static function.


The pointer size to a virtual function is the same as that to a non-virtual function. It is not the same as that to a static (or free) function. At least with gcc on 64 bit Linux regular function pointers have 8 bytes and member function pointers have 16 bytes.

Quote

It was only the 16-bit and 8-bit compilers that made the distinction between a pointer and a long pointer.


That's a different issue though. As I said, at least on some implementations¹, member function pointers store more information than just the address of the function, so they're really not just pointers.

¹ I'm not sure whether it's possible to implement member function pointers without additional space in general. I can think of one way, but I haven't entirely thought this through yet and I don't know how that would play together with multiple inheritance.
Was This Post Helpful? 1
  • +
  • -

#7 ccubed  Icon User is offline

  • It's That Guy
  • member icon

Reputation: 164
  • View blog
  • Posts: 1,416
  • Joined: 13-June 08

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 08:50 AM

Sepp, as usual, has done a good job of explaining your question, but as an aside, if I was asked this kind of question I would gather one of two things about the interviewer: 1) He's trying to use buzzwords without actually knowing what they mean or 2) He's trying to find out if you're the kind of person who uses buzzwords without actually knowing what they mean. In this case, since you said you were 'asked' to 'investigate' the difference between the two so that you had a good grasp of 'any and all C/C++ concepts' then I'm going to go with 1.

Basically, what I'm getting at is: Whoever asked you this question is going to be that guy who stands over your shoulder, pretends he knows what he is doing and constantly informs you of ways to 'improve' your code.

This is of course my opinion, but let us know what happens.

This post has been edited by ccubed: 05 September 2013 - 08:51 AM

Was This Post Helpful? 0
  • +
  • -

#8 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2579
  • View blog
  • Posts: 4,114
  • Joined: 21-June 11

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 09:01 AM

Actually on second thought, virtual and non-virtual function pointers could be different after all. They do have to have the same size, but it would be possible for them to contain some kind of flag indicating whether the function is virtual not. If that flag is false, it could then contain the address of the function and otherwise it could contain a vtable offset. In fact that really seems like the most obvious way to implement it, now that I think about it.

This post has been edited by sepp2k: 05 September 2013 - 09:02 AM

Was This Post Helpful? 0
  • +
  • -

#9 ccubed  Icon User is offline

  • It's That Guy
  • member icon

Reputation: 164
  • View blog
  • Posts: 1,416
  • Joined: 13-June 08

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 09:13 AM

View Postsepp2k, on 05 September 2013 - 10:01 AM, said:

Actually on second thought, virtual and non-virtual function pointers could be different after all. They do have to have the same size, but it would be possible for them to contain some kind of flag indicating whether the function is virtual not. If that flag is false, it could then contain the address of the function and otherwise it could contain a vtable offset. In fact that really seems like the most obvious way to implement it, now that I think about it.


I don't think the compiler actually cares about that. I believe the compiler would most likely just rely on a fall back system for functions that could be overwritten.

IE: in the case of +
Does ClassName.Operator+ exist in definition?
if yes: Run it
if no: run ObjectType.Operator+

But I could be horribly wrong too.

Edit: I am apparently horribly wrong. The compiler seems to use a Virtual Table at Compile Time.

This post has been edited by ccubed: 05 September 2013 - 09:16 AM

Was This Post Helpful? 0
  • +
  • -

#10 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1853
  • View blog
  • Posts: 6,671
  • Joined: 19-February 09

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 09:29 AM

When you use Polymorphism you use a base class pointer to possibly point to a derived class.

So it is not necessarily known which function (base or derived) will be used at compile-time. So a virtual table is used at run-time to keep track of which function is to be used.

Virtual method table
Was This Post Helpful? 0
  • +
  • -

#11 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2579
  • View blog
  • Posts: 4,114
  • Joined: 21-June 11

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 09:44 AM

View Postccubed, on 05 September 2013 - 06:13 PM, said:

I don't think the compiler actually cares about that. I believe the compiler would most likely just rely on a fall back system for functions that could be overwritten.

IE: in the case of +
Does ClassName.Operator+ exist in definition?
if yes: Run it
if no: run ObjectType.Operator+


(I assume ClassName is supposed to be a subtype of ObjectType here, right?)

The compiler doesn't know which class a given object has if it's accessed through a pointer or reference. That's the whole point of virtual functions. What you're describing is just normal non-virtual function lookup. Unless you're saying that those steps are performed at runtime, in which case: doing this would require keeping track of way more type information at runtime than implementations actually do and the result would be slower than vtables.
Was This Post Helpful? 0
  • +
  • -

#12 JSolnit  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 04-September 13

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 09:51 AM

Wow, I'm glad some of you more experienced folks weighed in and I can tell that I still have much to learn about virtual functions in general. However, and I encourage you all to correct me if I'm misinformed or not describing this accurately, I believe member function pointers and virtual member function pointers are definitely of different sizes.

First, I would refer anyone interested in knowing what I'm basing this conclusion on to have a look at this article: http://www.codeproje...astest-Possible

I acknowledge that it is a little over 8 years old, but I believe the results are still valid (particularly the subsection on "Implementations of Member Function Pointers"). The author clearly uses sizeof() to evaluate the size of various member types (virtual and non-virtual member functions among them) on a pretty wide array of compilers and architectures. He even goes into some detail on how specific compilers use "tricks" of their own design to allocate memory based on the nature of the class containing the member being pointed to (i.e. does it contain virtual members, does it inherit from multiple classes, etc.).

To not rely on just one source: http://gcc.gnu.org/o...-functions.html

That is directly from the online gcc documentation on compiler implementation. It corroborates what I have come to believe is true: on almost all compilers, a member function pointer is bigger than a function pointer. In addition, a member function pointer is bigger than a pointer to a data member from the same class. And a virtual member function pointer is bigger still.

Here's why, as I understand it. In the very simplest case scenario (a pointer to a non-virtual member) the pointer needs to be represented as at least a set of two pointers: one holding the physical memory address of the member function and a second which holds the this pointer. However, the pointer to member has to also support virtual member functions, members of objects which inherit from multiple bases, and members of virtual bases. Thus, a pointer to member can contain up to four fields in certain cases. For instance, for a typical pointer to virtual member function must contain a pointer to the correct vtable for the class of objects to which it will point, and the index within the vtable where the pointed to function resides. Furthermore, with multiple inheritance, which this pointer to use can’t be determined until a call is made. Thus, the vtable itself contains the address of each virtual function of the class object to which it belongs, and the virtual_delta (how many bytes need to be added to the provided this pointer to convert it to the this pointer needed by the version of the function that will ultimately be used).

I'm fairly certain there is more to it and I've probably butchered terminology in several places, but can anyone explain why my understanding is incorrect to me?

Also, thanks to everyone for their insightful posts and I just wanted to update everyone on what I've found poking around that has lead me to this conclusion. Also, http://www.informit....plus&seqNum=142 confirms what the other links indicated (got to have multiple sources!).
Was This Post Helpful? 0
  • +
  • -

#13 ccubed  Icon User is offline

  • It's That Guy
  • member icon

Reputation: 164
  • View blog
  • Posts: 1,416
  • Joined: 13-June 08

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 09:53 AM

View Postsepp2k, on 05 September 2013 - 10:44 AM, said:

(I assume ClassName is supposed to be a subtype of ObjectType here, right?)

The compiler doesn't know which class a given object has if it's accessed through a pointer or reference. That's the whole point of virtual functions. What you're describing is just normal non-virtual function lookup. Unless you're saying that those steps are performed at runtime, in which case: doing this would require keeping track of way more type information at runtime than implementations actually do and the result would be slower than vtables.


ClassName being the name of the class and classes are objects, so yes. It's just that by ObjectType I meant the underlying type of whatever the compiler is trying to perform Operator+ on. Whereas with ClassName I was impressing that it was specifically calling the Class's implementation of Operator+.

Anyways, I don't purport to be an expert on compilers so I was horribly wrong. It's interesting to know.
Was This Post Helpful? 0
  • +
  • -

#14 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2579
  • View blog
  • Posts: 4,114
  • Joined: 21-June 11

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 10:11 AM

View PostJSolnit, on 05 September 2013 - 06:51 PM, said:

I believe member function pointers and virtual member function pointers are definitely of different sizes.


All pointers to member functions of the same class, given the same signature, have the same size regardless of whether or not they're virtual. I missed the "of the same class" in my earlier answer, but the rest of the logic still holds. A pointer to a virtual function of a class and a pointer to a non-virtual function of the same class can not have different sizes.

Quote

First, I would refer anyone interested in knowing what I'm basing this conclusion on to have a look at this article: http://www.codeproje...astest-Possible

I acknowledge that it is a little over 8 years old, but I believe the results are still valid (particularly the subsection on "Implementations of Member Function Pointers"). The author clearly uses sizeof() to evaluate the size of various member types (virtual and non-virtual member functions among them) on a pretty wide array of compilers and architectures. He even goes into some detail on how specific compilers use "tricks" of their own design to allocate memory based on the nature of the class containing the member being pointed to (i.e. does it contain virtual members, does it inherit from multiple classes, etc.).


Yes, but that's exactly the point: A compiler can use tricks if it knows that the class doesn't have virtual member functions. But if it does have them, pointer to non-virtual functions of that class have the same size as those to virtual member functions.

Quote

Here's why, as I understand it. In the very simplest case scenario (a pointer to a non-virtual member) the pointer needs to be represented as at least a set of two pointers: one holding the physical memory address of the member function and a second which holds the this pointer.


No, a member function pointer does not hold the address of the receiver. The receiver is supplied when the function is called. And as the article you cited demonstrated, a member function pointer to a class that does not have virtual member functions does take exactly as much space as a normal function pointer on some compilers.

PS: Note that the table in the article you linked only compares pointers to member functions of different classes. I.e. it compares "pointer to member function of class without virtual functions" to "pointer to member function of class with virtual functions" - not "pointer to virtual member function" to "pointer to non-virtual member function".

This post has been edited by sepp2k: 05 September 2013 - 10:13 AM

Was This Post Helpful? 1
  • +
  • -

#15 JSolnit  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 04-September 13

Re: Pointers to virtual vs. non-virtual member functions

Posted 05 September 2013 - 11:13 AM

View Postsepp2k, on 05 September 2013 - 10:11 AM, said:

All pointers to member functions of the same class, given the same signature, have the same size regardless of whether or not they're virtual. I missed the "of the same class" in my earlier answer, but the rest of the logic still holds. A pointer to a virtual function of a class and a pointer to a non-virtual function of the same class can not have different sizes.


Okay, sepp2k, I was still a little unclear, so I took the plunge and wrote some simple code to see if I could compare sizes of member pointers. Could you look at the code and the output and tell me, is this proving your point about pointers to members of the same class having the same size, or am I being naive in my approach?

By the way, I'm using Visual Studio 2010 on a 64 Bit Windows 7 installation, if that matters.

#include<iostream>
#include<stdlib.h>

using namespace std;

class BaseClass {

public:
	int x;
	void NonVirtF() { cout << "Base class non-virtual function/n"; };
	virtual void VirtF() { cout << "Base class virtual function/n"; };
};

class DerivedClass: public BaseClass {

public:
	virtual void VirtF() { cout << "Derived class virtual function/n"; };
};

int main() {

	int BaseClass::*pmi = &BaseClass::x;			
	void (BaseClass::*pnvmf)() = &BaseClass::NonVirtF;
	void (BaseClass::*pvmf)() = &BaseClass::VirtF;

	int memInt = sizeof (pmi); 
	int memNonVirt = sizeof (pnvmf); 
	int memVirt = sizeof (pvmf);

	cout << "Size of pointer to member int = " << memInt << endl
		<< "Size of pointer to member non-virtual function = " << memNonVirt << endl
		<< "Size of pointer to member virtual function = " << memVirt << endl;

}



OUTPUT:
Size of pointer to member int = 4
Size of pointer to member non-virtual function = 4
Size of pointer to member virtual function = 4


Is it strange that they are all 4 bytes? Any suggestions on how to produce pointers of different sizes (assuming I actually did what I think I did here) so I might look at the contrasting conditions which led to such an outcome?
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2