I think the statement below is wrong or am I missing something?

The following paragraph was extracted from page 420 of Stroustup's book "C ++ Programming Language" (third edition):

Since the pointer to the virtual member (s in this example) is a kind of offset, it does not depend on the location of objects in memory. Thus, a pointer to a virtual element can be safely transferred between in different address spaces, while using the same object layout and both. Like pointers to ordinary functions, pointers to non-virtual member functions cannot be exchanged between address spaces.

I dispute the last sentence in this paragraph. Below you will find a code fragment in which pointers to non-virtual functions, foo() and foo1() exchanged between one base object a and a derived object b , without a problem.

What cannot be done is overloading any of the functions in the database, foo() or foo1() , in a derived class, because in this case the compiler will throw an error, as shown below.

 #include <iostream> class A { int i; public: A() : i(1) {} void foo() { std::cout << i << '\n'; } void foo1() { std::cout << 2 * i << '\n'; } }; class B: public A { int j; public: B() : A(), j(2) {} // void foo() { std::cout << j << '\n'; } }; int main() { typedef void (A::* PMF)(); PMF p = &B::foo; // error C2374: 'p' redefinition, multiple initialization // if foo() is overloaded in B. PMF q = &B::foo1; B b; (b.*p)(); (b.*q)(); A a; (a.*p)(); (a.*q)(); } 
+6
source share
2 answers

This sentence is true: in a (standard) C ++ program, or rather a process, it has exactly one address space. So, as ulidtko pointed out, this proposal relates to the possibilities of exchanging pointers to virtual and non-virtual member functions between the address spaces of different processes.

A non-virtual member function of a class is pretty much a standard function with an implicit argument for the object you are calling it for (this pointer). Thus, when loading it is assigned some address in the address space of your process. Where exactly this ends in your address space, of course, depends on your platform and whether this member function is part of a dynamically linked library. The fact is that for two processes this is not necessarily the same address. Thus, passing a pointer to and then executing such a function in another process will potentially "bring your machine to work (TM)."

A virtual member function is still almost the same as a non-virtual member function, as in "some memory address to which you go to execution and pass this pointer to it", but it receives a call through the virtual function table ( vtable) instead of direct. Thus, a pointer to a virtual member function is just an index in your object virtual function table. Calling this function does something in accordance with โ€œtaking a pointer to an objectโ€, possibly increasing the pointer to go to the vtable object and go to the address at the specified index of this table, passing the address of the object itself as this pointer. โ€Thus, this indirect use via vtable allows you to exchange a pointer to a virtual member function between address spaces.

Disclaimer: I am slightly leaning over my "I really know what I'm talking about" - there is a comfort zone here. Therefore, if I have simplified something or something else, however, while distributing false information, do not hesitate to drop my answer;).

+1
source

The pointer will always exist as virtual memory, so that is correct, you can check the address and see that there is no physical pointer to the memory address

Since the pointer to the virtual member (s in this example) is a kind of offset, it does not depend on the location of objects in memory. Therefore, a pointer to a virtual member can be safely transferred between different address spaces, as long as the same object layout is used in both. Like pointers to ordinary functions, pointers to non-virtual member functions cannot be exchanged between address spaces.

0
source

All Articles