Re: Is it legal code?
"James Kanze" <james.kanze@gmail.com> wrote in message
news:b4306fba-68dd-44e6-a035-c42a6b44b514@4g2000yqo.googlegroups.com...
On Feb 21, 12:46 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
"James Kanze" <james.ka...@gmail.com> wrote in message
news:0e0dc254-eccb-42aa-8ab7-35db4c4218e1@w21g2000yqm.googlegroups.com...
[...]
I don't quite follow you here. If I have a function:
void f(int&);
, it's undefined behavior for me to call f without a an object
of type int.
You must've forgot we are talking about *member functions*.
So what's the difference, with regards to your argument.
The difference is that the standard defines a rule for nonstatic member
functions. The same rule does not apply to normal functions.
The only difference defined by the standard is that nonstatic
member functions have an implicit first parameter, of type T&
(or T const&).
You said yourself:
"A member function has a special calling syntax, and special access rights
to member data".
Also:
A member function must be called on an object , or it produces UB, a normal
function does not have this requirement.
A member function is declared in a class scope, a normal function is not.
The function f(int&) still "exists". For some
definition of "exists"---this is getting a bit too metaphysical
for me. One could argue that in C++, only "objects" exist, and
references and functions aren't objects, so can't "exist".
An object(instance of a class type) has a lifetime, it exists
for the duration of its lifetime. Because C++ disallows
calling nonstatic member functions, without an object of , or
derived from, the respective class type. A non static member
function cannot exist unless an object exists.
What does the ability to call a function have to do with its
existance? To call a function (any function), you have to have
objects which correspond to its parameters, or at least to those
parameters which require lvalues. If "existance" of a function
has any meaning related to execution, then the only reasonable
definition for "exists" is "has an address which can be taken";
addresses determine, for example, whether we have one object or
two. And you can take the address of any function (member or
non-member) at any time during execution, regardless of what
objects may or may not exist.
Because the function was declared as a member of an
object-type, if you directly invoke this function without an
object you'll produce UB.
How is that different from calling any other function which
takes a reference without an object that the function refers to?
What does a reference have to do with anything?
When considering the existence of a NSMF, you must take into account the
object on which it was called.
Why? It obeys exactly the same rules as a static member
function, or a free function.
Because the standard lays down some rules specific to NSMF's.
A nonstatic member function has different rules than a static member
function or ordinary function.
For example consider two different objects both processing the
same member function, at exactly the same time. Its the same
function definition for each NSMF but its certainly not the
same function that's executing.
It most certainly is the same function. The standard requires
it.
The local variables,parameter and return value in function1 are not the same
as those in function2, they are two seperate processes .
Plus you have access rights to member data.
To what do you refer when you suggest the standard requires them to be the
same?
I understand your POV with the basic old mathematical function concept
i.e:
input --> function process --> output., that all function are more or
less
handled the same for a given architecgture/calling convention. To clairfy
what i mean is the register/stack state is almost identical for each
function invocation, the only thing that changes may be a few variable
values.
But when we look at NSMF's then things become a little bit different and
addressing and such becomes a little more complex vtables etc. Imagine
two
different objects invoking their same respective NSMF's simultaneously,
each
is a completely different process. Thus when speaking of NSMF's I think
it
is a valid concept that the existence of the function starts when invoked
and ends on return.
ALso the implementation is not bound to implement the
mechanics in any defined way. So addressing and such is very
imp-specfic. As an example: In some cases it may be more
optimal for an implementation to have 2 versions of the same
function, or something like this.
An implementation is certainly allowed to make as many copies of
the function as it wishes. Member or otherwise. On the other
hand, the standard requires that all pointers to the function
compare equal. Member or otherwise. Even if the implementation
makes many "copies" of the function (as it typically does if the
function is inline), it has to ensure that all of the pointers
to the function compare equal.
This is very close, if not identical, with the OO concept of
identity. In C++, if two addresses (of objects) compare equal,
they are the same object. Comparison of address is the way you
test identity in C++.
ok so with:
#include <iostream>
class Base1{public: virtual void foo()=0; virtual void bar()=0;};
class Derived: public Base1{
public:
void foo(){std::cout<<"in foo"<< std::endl;}
void bar(){std::cout<<"in bar"<< std::endl;}
};
int main()
{
void (Base1::*fp1)() =&Base1::foo;
void (Base1::*fp2)() =&Base1::bar;
Base1* b1=new Derived;
std::cout<< "fp1 points to: " << fp1 << std::endl;
std::cout<< "fp2 points to: " << fp2 << std::endl;
(b1->*fp1)();
(b1->*fp2)();
}
Does this not prove the address can be the same but the functions are
different?