Is it legal code?

T

thomas

Is it legal to invoke a (non static) member function without an object?

I read something in the C++ standard that it may not be standard compliant
code to invoke a (non static)member function directly from a pointer.

Nope. You must create an object to use its members unless the member
is declared static.
 
I

itaj sherman

--I don't think you read carefully everything I said.

No I try to but sorry please explain

You propose a few questions about nonstatic member functions. What I'm
saying is that there is no reason for these questions to be
specifically about nonstatic member function. These questions can/
should be asked about all functions the same. There is nothing about
nonstatic member functions that makes a difference with respect to
these questions.

The difference between nonstatic member functions and other functions
is in syntax and some name lookups:

call syntax:
arg0.foo( arg1, arg2 );
instead of:
foo( arg0, arg1, arg2 );

declaration syntax:
Ret Par0::foo( Par1 arg1, Par2 arg2 );
instead of:
Ret foo( Par0& arg0, Par1 arg1, Par2 arg2);

And because it's not possible by the syntax to give a name for arg0,
use a keyword 'this', which could be a reference, but was decided to
be the equivalent const pointer to the object.
So as if the function begins with:
Par0* const this = &arg0;
* Except that a temporary can bind to a hipothetic non const reference
arg0. But nobody in this thread was talking about the temporaries
difference.

Note that:
arg0->foo( arg1, arg2 );
is equivalent to:
(*arg0).foo( arg1, arg2 );

To assure some terminology:
A function of arity N, has N parameters (in CS sense). Non-static
member function, can only be of arity 1 or bigger, and their first
parameter/argument is written before the fucntion identifier (instead
of inside the braces, both declaration and call).

Now I'll show how a few of the questions could be frased in the more
general sense of functions, instead of only nonstatic member
functions:

1)
From Shaub's post:
It is undefined behavior if you do so.
struct A { void f() { } };
int main() { ((A*)0)->f(); }
Undefined. No object.

struct A {};
void foo( A& );
int main() { foo( *((A*)0) ); }

This is undefined behaviour for the same reason. It has nothing
specific to do with it being a nonstatic member function.

2)
Your first question
Is it legal to invoke a (non static) member function without an object?

can be refrased:
Is it legal to invoke a function with a reference parameter without an
object?

3) and the grand final:
It follows that if an object(or derived object) does not exist then it is
undefined behaviour to call its respective nonstatic member function?
Therefore it must be true that a member function does not exist without an
object.

It follows that if an object(or derived object) does not exist then it
is
undefined behaviour pass it to a reference parameter of any function?
Therefore it must be true that a function with reference parameter
does not exist without an
object (for that parameter).

itaj
 
I

itaj sherman

I hope you misunderstood me.


I agree, but the same thing is true for all functions, not just
nonstatic members:
Yes, please act in a troll-way.

So what do you mean by that?????????????

itaj
 
P

Paul

< snip >

--Yes. It will be compiled by standard-compliant compiler so it is legal
--code and it will run with undefined results so it is invalid code.

This is where I am uncertain, the definition of 'legal code' and 'valid
code'. This seems a pretty fair
description you have given . Is this actually defined anywhere or is it just
the generally accepted definition?

Ty for your replies , I have snipped alot to make my indenting problems
easier to handle.
 
P

Paul

itaj sherman said:
You propose a few questions about nonstatic member functions. What I'm
saying is that there is no reason for these questions to be
specifically about nonstatic member function. These questions can/
should be asked about all functions the same. There is nothing about
nonstatic member functions that makes a difference with respect to
these questions.
It seems inconceivable that a normal function is called on an object, I
don't see how this question can be asked for a normal function.
The difference between nonstatic member functions and other functions
is in syntax and some name lookups:

call syntax:
arg0.foo( arg1, arg2 );
instead of:
foo( arg0, arg1, arg2 );

declaration syntax:
Ret Par0::foo( Par1 arg1, Par2 arg2 );
instead of:
Ret foo( Par0& arg0, Par1 arg1, Par2 arg2);

And because it's not possible by the syntax to give a name for arg0,
use a keyword 'this', which could be a reference, but was decided to
be the equivalent const pointer to the object.
So as if the function begins with:
Par0* const this = &arg0;
* Except that a temporary can bind to a hipothetic non const reference
arg0. But nobody in this thread was talking about the temporaries
difference.

Note that:
arg0->foo( arg1, arg2 );
is equivalent to:
(*arg0).foo( arg1, arg2 );

To assure some terminology:
A function of arity N, has N parameters (in CS sense). Non-static
member function, can only be of arity 1 or bigger, and their first
parameter/argument is written before the fucntion identifier (instead
of inside the braces, both declaration and call).

Now I'll show how a few of the questions could be frased in the more
general sense of functions, instead of only nonstatic member
functions:

1)
From Shaub's post:



struct A {};
void foo( A& );
int main() { foo( *((A*)0) ); }

This is undefined behaviour for the same reason. It has nothing
specific to do with it being a nonstatic member function.
The above is using a null pointer of type A*, and you show that the reason
A->memb_func() fails is the reason memb_funct(A) fails when A is a null
pointer passed as a reference., yes ?
But this is not the same as:
func_pointer = A::my_memb_func;
invoke func_pointer.

So the question is not the same for normal functions and member functions.

2)
Your first question

can be refrased:
Is it legal to invoke a function with a reference parameter without an
object?
I disagree with your conclusion that these two things are the same.
 
J

James Kanze

"gwowen" <[email protected]> wrote in message
--If the pointer points to an object that still exists, its fine.
--Otherwise, no. Essentially the same as dereferencing the pointer.
Firstly sorry ABOUT INDENTING PROBS.
Is it the case that a function pointer can be an object becuse its not
actually a function , its a pointer.?

I'm not sure what the context is, but yes: pointers (including
pointers to functions, and pointers to members) are objects. In
C++; other languages may consider them differently.
I'm not sure it helps the situation anyway because what I was trying to
deduce was whether or not a (nonstatic)member function is allowed to be
called without the presence of an object.

A non-static member cannot be called without an instance of the
class (an object). As others have pointed out, a non-static
member function has an implicit first argument; at least for
overload resolution (and I think more generally), it has type
MyClass& (or MyClass const&, if the function is const). (Inside
the function, the type of this is a pointer, but this is mainly
because member functions were added before references; in modern
C++, it would make more sense for this to have a reference
type.)
I think object in this context is (an instance of class type),
not purely an object in the context used within the C++
standard.

In this case, it doesn't make a difference, since only class
types can have member functions.
 
P

Paul

itaj sherman said:
I hope you misunderstood me.



I agree, but the same thing is true for all functions, not just
nonstatic members:
I disagree with you see the other more detailed thread.
So what do you mean by that?????????????
It's not a very nice thing to say as you have raised a valid argument
,whether I disagree with it or not.
 
J

James Kanze

"gwowen" <[email protected]> wrote in message
--If the pointer points to an object that still exists, its fine.
--Otherwise, no. Essentially the same as dereferencing the pointer.
So given that the following is true:
"If a nonstatic member function of a class X is called for an
object that is not of type X, or of a type derived from X, the
behavior is undefined."
It follows that if an object(or derived object) does not exist then it is
undefined behaviour to call its respective nonstatic member function?
Therefore it must be true that a member function does not exist without an
object.

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. 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".
 
P

Paul

No. That is simply not a syllogism. "X is undefined behaviour" is not
equivalent to "The constituent parts of X do not exist."
It is undefined behaviour to call strlen(const char *) on a pointer
that does not point to a valid NULL terminated string. That does not
mean that the strlen() function does not exist until a valid string
exists, and that it ceases to exist when all such strings go out of
scope.
According to the standard you cannot have any strlen without an object of ,
or derived from , string.
That is assuming strlen is defined as a non static member function of
string, in class string.
Setting aside the peculiar ontological implications of such a
deduction, you can (for example) take the address of "strlen()".

Consider with a more simple example:
class C_type{
public:
void foo(){};
};

int main(){
C_type* obj1 = new C_type();
obj1.foo(); /*foo existshere*/
delete obj1;
/*foo no longer exists*/
}

If we do not have an instance of C_type then we do not have any foo()'s.
The function definition will still exist someplace so if another C_type is
created another foo can be invoked.

I aggree it is not strictly true to say the function no longer exists
because it is possible to directly call the function with a function
pointer. But since this is not valid according to the C+ standard, it can be
said , as far as the standard is concerned, that the function does not exist
unless an object of the class type exists.
 
I

itaj sherman

It seems inconceivable that a normal function is called on an object, I
don't see how this question can be asked for a normal function.

This is what I tried to explain. You say "called on an object" instead
"pass an object argument to the first parameter", but they mean the
exact same thing.
The above is using a null pointer of type A*, and you show that the reason
A->memb_func() fails is the reason memb_funct(A) fails when A is a null
pointer passed as a reference., yes ?

Yes.
And if you understand this, I think you should understand the rest of
what I said, if you read it carfully.
But this is not the same as:
func_pointer = A::my_memb_func;
invoke func_pointer.

What is "func_pointer", and what is "invoke func_pointer"?
If you invoke a function (even through a pointer) you have to pass
arguments to all parameters, and you should state how you do it here.
That includes the special argument in case of a nonstatic member
function
So the question is not the same for normal functions and member functions.

Which question?!
All the ones you talked about are.
Syntactic and name lookups are different.
I disagree with your conclusion that these two things are the same.

I know you disagreed. This is exactly why I tried to explain how they
are the same, with respect to your issue.
I tried my best to explain. I think if you were able to grasp this
concept in a general way (instead just nonstatic members), it would
help you clear the confusions for you and everyone else.

itaj
 
Ö

Öö Tiib

< snip >

--Yes. It will be compiled by standard-compliant compiler so it is legal
--code and it will run with undefined results so it is invalid code.

This is where I am uncertain, the definition of 'legal code' and 'valid
code'. This seems a pretty fair
description you have given . Is this actually defined anywhere or is it just
the generally accepted definition?

I am also uncertain about terminology. Let me try to elaborate.

Language contains that feature so it is legal code. People use that
feature sometimes knowingly. For example they reinterpret a buffer of
bytes as object of some plain old data class and call member function
for it (or some non-member function that uses it). If the alignment
and layout of the bytes matches with real object then it works. I do
not know any platforms where it does not work.

When it is not plain old data class or the bytes do not match with
real object's invariant then it is undefined by standard. It may be
specified for implementation, then it is implementation-specific.

For example: The buffer reinterpreted into object contains byte with
value 42 at position where there should be a bool data member in
object. bool however may have only values true or false (1 or 0).
Called member function that reads that bool data member still likely
runs. Only that it will behave like that bool has value true or has
value false or has both values or has neither of them, depending on
compiler implementation. I don't know implementation that specifies
behavior of bool with underlying binary value 42 so it is invalid
program with programming error in it on all platforms i know of.
 
P

Paul

James Kanze said:
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*.
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.
 
J

Johannes Schaub (litb)

itaj said:
I hope you misunderstood me.



I agree, but the same thing is true for all functions, not just
nonstatic members:

The question then is whether you still "invoke a (non static) member
function without an object". If you interpret the question as meaning "with
arguments that don't represent objects" then the question becomes moot. Is
the following an answer?

void f() { }
f(); // yes you can!

It's pretty clear to me the only sense you can get out of the question is
when you interpret "without an object" to refer to the implied object
argument that "*this" refers to.
So what do you mean by that?????????????

I have shown

1) How you call a non-static member function without an object (subject of
the question)
2) That it is undefined behavior (I did not quote the spec - I left that as
an exercise to the reader).

You then show something completely unrelated (calling a free function with a
null reference as an argument). Which is of course also undefined behavior,
but has nothing to do with the question nor with the answer ("to invoke a
(non static) member function without an object"). Why does that
question/this answer have not specifically to do with nonstatic member
functions?
 
J

Johannes Schaub (litb)

Johannes said:
The question then is whether you still "invoke a (non static) member
function without an object". If you interpret the question as meaning
"with arguments that don't represent objects" then the question becomes
moot. Is the following an answer?

void f() { }
f(); // yes you can!

An just for the record. That would not be a "nonstatic member function".
 
I

itaj sherman

Ok, it was a misunderstanding. I thought you would agree with me that
what I said is related. I'll try to explain what I meant, as I said in
my other posts in this thread. You might still not agree with me that
it is related, then I can only apologize that I used the momentum of
your post to make my point.
Sorry.
The question then is whether you still "invoke a (non static) member
function without an object". If you interpret the question as meaning "with
arguments that don't represent objects" then the question becomes moot. Is
the following an answer?

My only point was that they are idealy the same question. That there's
nothing special about nonstatic member functions with respect to this
issue.
And I think that limiting the discussion to only the nonstatic member
case, is at least unnecessary but can also cause confusion due to
extra assumptions.
As I said elsewhere the difference of nonstatic member functions are
in syntax and name lookup mainly.

To explain my POV I'll clear that:
For example, a nonstatic member function with 2 extra paramters inside
the braces, is actualy an 3-ary function (in CS sense), whose first
parameter is written outside the braces (with the member lookup
syntax).

i.e
arg0.foo( arg1, arg2 );
instead:
foo( arg0, arg1, arg2 );

declared:
Par0::foo( Par1, Par2 );
instead:
foo( Par0&, Par1, Par2 );
void f() { }
f(); // yes you can!

It's pretty clear to me the only sense you can get out of the question is
when you interpret "without an object" to refer to the implied object
argument that "*this" refers to.

And my demonstration required to replace your function:
void A::f(); //with arity 1
With my example:
void f( A& ); //also arity 1

and not
void f(); //with arity 0
which wasn't my example.

And then I can say that my function, which is also arity 1, cannot be
called "without an object" for it's first parameter.
And this requirement has nothing to do with the differences in syntax
between nonstatic members and other functions.

Please also look at my other posts to understand what I mean, and why
I think it is important for this thread.

itaj
 
G

gwowen

strlen without an object of ,
or derived from , string.

strlen(const char*) is a C++ standard function, the same as the C
standard function strlen(const char*). If you don't know that, you
should probably stop trying to make weird ontological assertions about
what is and is not said in the standard, as you don't appear to be
sufficiently familiar with it.
That is assuming strlen is defined as a non static member function of
string, in class string.

Which it isn't. It's a stand-alone function, but its still undefined
behaviour to call it on a pointer when that pointer does not point to
a NULL-terminated string.

Consider the following:

int main()
{
char* foo = new char(20);
/* q declared int, rather than std::size_t in order to save myself
typing */
int q = strlen(foo);
std::cout << "The length of foo is " << q;
}

The above program invokes undefined behaviour.
None of its constituent parts are non-existent.
Therefore, your syllogism "UB -> Non-existence" is wrong.
 
I

itaj sherman

You must've forgot we are talking about *member functions*.


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.

Does the following also work?

An object(instance of a class type) has a lifetime, it exists for the
duration of its lifetime.
Because C++ disallows calling global functions with a class reference
parameter, without an object of , or derived from, the respective
class type. Such function cannot exist unless an object exists.

struct A {};
void foo( A& )
{
}
// foo does not exist here.

int main()
{
//foo does not exist here either.
A a;
// aah there you go, now foo exists.
foo( a );
}

itaj
 
I

itaj sherman

struct A {};
void foo( A& )
{}

// foo does not exist here.

int main()
{
//foo does not exist here either.
A a;
// aah there you go, now foo exists.
foo( a );

}

Actually even better:

struct A
{
public: void bar()
{
}
};

void foo( A& )
{
}

// foo and bar don't exist here.

typedef void (*FuncPtr)( A& );
typedef void (A::*MemberFuncPtr)();

int main()
{
//they don't exist here either.
FuncPtr x = &foo;
MemberFuncPtr y = &A::bar;
//OMG, they don't yet exist even here.
A a;
// aah there you go, an object exists, and now the functions also
exist.
foo( a );
a.bar();
}

itaj
 
I

itaj sherman

You must've forgot we are talking about *member functions*.

Why?
Why you only stick to nonstatic member function?
Why can't you deal with this issue generally about all functions?
IMO, if you do that it will clear a lot of the confusion.

itaj
 
P

Paul

strlen without an object of ,
or derived from , string.

strlen(const char*) is a C++ standard function, the same as the C
standard function strlen(const char*). If you don't know that, you
should probably stop trying to make weird ontological assertions about
what is and is not said in the standard, as you don't appear to be
sufficiently familiar with it.
That is assuming strlen is defined as a non static member function of
string, in class string.

Which it isn't. It's a stand-alone function, but its still undefined
behaviour to call it on a pointer when that pointer does not point to
a NULL-terminated string.

Consider the following:

int main()
{
char* foo = new char(20);
/* q declared int, rather than std::size_t in order to save myself
typing */
int q = strlen(foo);
std::cout << "The length of foo is " << q;
}

The above program invokes undefined behaviour.
None of its constituent parts are non-existent.
Therefore, your syllogism "UB -> Non-existence" is wrong.
-----------------------------------------------------------------------------
dam this newsreader
----------------------------------------------------------------------------

You misunderstand me , I don't mean that anything that produces undefined
behaviour does not exist.

Perhpas this is a better way to phrase it:
The function is only defined if an object exists so if there is no object
there is no defined function
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top