function calls

R

Rolf Magnus

Paul said:
This is psuedo code, you can change the object 'this' points to using any
code you like, obviously that's assuming the object is not stored in
read-only memoery.

The above code doesn't change the object, it changes the this-pointer.
Sorry I should've made a specific note about psuedo code. I presumed it
was obvious following from the context of my previous example.

Actually, I don't know what that code is supposed to tell me.
The constantness is not rellevant to understand the point as code can be
written to overcome that.

Not in a standard compliant way.
Neither the stack nor the heap is read only. The object 'this' points to
is likely to be in one of these areas, therefore overwriteable.

You should decide whether you want to look at it from the C++ standard point
of view or from "behind the scenes". The heap, the stack and the concept of
read only memory are not defined in C++. They are rather an implementation
detail. On that level, non-static member functions are implemented the same
as non-member functions, but with the address of the object as a hidden
parameter.
On the C++ level on the other hand, you have a pointer that is initially
declared const, and the C++ standard says that casting away constness of
such an object results in undefined behavior. So you cannot modify the this-
pointer in a member function, and neither can you modify anObj in:
 
J

James Kanze

"James Kanze" <[email protected]> wrote in message
--Not exactly the same, but fundamentally the same.
Ah ok sorry misunderstanding.
--The C++ standard does specify significant differences in the
--calling syntax (e.g. in 5.2.2).
Ok so this is the syntaxical rules we must obey, is it not?

It's just syntax. It's arbitrary. And superficial. (Other
languages use different syntax to achieve largely the same
thing. And there have been proposals---which I would
support---to unify the C++ syntax, so that for a member
function, obj.func() and func(obj) have exactly the same
meaning.)
-- Beyond that, however, it
--requires the this pointer to be initialized exactly as if it
--were a reference to an object (except that it is initialized
--with pointer type, and not with reference type). And it
--certainly treats them the same in overload resolution. There's
--no fundamental difference between them.
Now I find what you say here slightly confusing.
You say "beyond that" which I take to mean ..Beyond the definition of the
standard, in your previous sentence.

Beyond simple syntax.
Then you go on about what the standard requires for
initialisation of the this pointer. Surely we must either
speak in terms of the standard or not, you seem to jump in and
out of standards context when it suits you.

I'm speaking purely within the context of the standard here.
The standard describes member functions as behaving
fundamentally like free functions with an additional implicite
argument. And for cause---it very definitely intends that an
implementation which does this be legal.
But ignoring that, what you actually speak about is initialisation of the
this pointer, which I presume is a pointer, yes?

Yes and no. It's certainly not a variable with pointer type,
since it's not an lvalue.
You seem to intepret the this pointer a reference, surely the this pointer
is not required to be converted to a refernece, this seems like an
unneccessarry converion forced upon a compiler i.e :
pointer -> reference -> pointer. (why?)

The semantics of the implicit argument used to initialize the
this pointer are the semantics of a reference, and the this
pointer behaves semantically like a reference: it cannot be
null, and it cannot be reseated. When asked why "this" is not
a reference, Stroustrup says "because references didn't exist
when it was introduced." In other words, if they had, this
would probably be a reference.
Don't get me wrong I understand what you are saying about the
underlying mechanics of a nonvirtual function call, but the
issue here is: Are we allowed to do this as per the C++ std,
which is the general concensus of this group to determine
proper C++ code.

Allowed to do what? The standard is carefully crafted so that
existing implementation techniques would be legal. The most
widespread (the only, as far as I know) technique for
implementing member functions is as a normal function with
an additional implicit argument. The standard is carefully
worded so that this implementation is legal. The result is that
member functions and non member functions are pretty much the
same thing, when viewed from a standards point of view.
--There are other subtle differences: a non-const member function
--can be called on a temporary, where as a non-const reference
--cannot be initialized with a temporary, for example.
I see again you introduce references , this obviously has seem to be a
requirement for you argument.
I don't see the need to have any references when calling a member function,
therefore this continued use of referneces in your demonstrations leads me
to believe there is something wrong.

I introduce references because the implicit argument used to
initialize the this pointer behaves like a reference.
Can you not give an example using simple pointers ?

No, because a simple pointer can be null, and it can be
reseated. This is a pointer for historical reasons, but except
for syntax, it behaves like a reference.
-- But in the
--other thread, you were looking for things that would make
--member functions fundamentally different from non-members.
I'm not looking for something to make them different , I know they are
different. I'm trying to understand why you think it's beneficial to think
of them as the the same.

Because they are fundamentally the same.
One word proves they're different ...virtual.

That's a different issue. Although the standard also describes
virtual functions as being fundamentally the same as any other
function. The only thing that differs is which function is
actually choosen. A sort of overloading, deferred to runtime.

Note that although C++ chooses to limit virtual functions to
members, there's no fundamental reason why this should be the
case.
As below we must respectively assume you are obviously not talking about
virtual functions
--Where as I fail to see anything but syntax differences between
--titi and tata in the following:
-- struct Toto
-- {
-- void titi() const;
-- friend void tata(Toto const&);
-- };
--This is, of course, an extreme case of similarity. But my point
--is that except for syntax, member functions have a series of
--characteristics that can, in specific cases, apply to non member
--functions as well.
Yes I agree.
But that syntax difference means we are not allowed to do the following, or
does it:
struct ObjT{
void mthd(){};
};
ObjT o;
mthd(o); /*I do not understand this is uncharted waters to me*/

That has been proposed. It was too late for C++98, and for some
reason, the proposal has not be followed up for C++0x. The
basic proposal was that o.mthd() and mthd(o) mean exactly the
same thing. (The proposal was never really studied, so there
could be significant problems with it.)
mthd(&o) /*or is this what you propose?its not a reference I know*/
o.mthd() /*my normal calling syntax*/
I don't know if any of the above is proper code I didn't try to compile
anything, please can you explain what is valid as per the standard.

The only point is that whether you write o.mthd() or mthd(o) is
purely syntax. (IIRC, Ada 95 chose the second form.) It has
nothing to do with what a function fundamentally is or is not.
 
P

Paul

Rolf Magnus said:
The above code doesn't change the object, it changes the this-pointer.
The above code doesnt do anything its psuedo code, it explains what real
code would do.
Actually, I don't know what that code is supposed to tell me.

If you are unable to understand then so be it I cannot it explain it any
simpler .

<snip>
 
P

Paul

James Kanze said:
It's just syntax. It's arbitrary. And superficial. (Other
languages use different syntax to achieve largely the same
thing. And there have been proposals---which I would
support---to unify the C++ syntax, so that for a member
function, obj.func() and func(obj) have exactly the same
meaning.)
What an idiotic statement to make.
The syntax *is* the language.
Beyond simple syntax.
What simple syntax? Not that language we call C++ you talking about . BTW
why does it have a differnet name from other programming languages? they're
all the same except for syntax..duh .

So I was correct you do jump in and out of the standards when you choose?
I'm speaking purely within the context of the standard here.
The standard describes member functions as behaving
fundamentally like free functions with an additional implicite
argument. And for cause---it very definitely intends that an
implementation which does this be legal.

You are not speaking in the context of the , show us where the standard
states what you claim.

I have provided a quote from the stantard that says a member function call
is different from a normal function.


I am really getrtting sick the brainless idiots in this newsgroup speaking
shit,
I'm on the verge of telling you to just go and **** off , your argument is
so idioticly unreasonable.

Yes and no. It's certainly not a variable with pointer type,
since it's not an lvalue.

Yes and no... I chose what I want when I want it to mean wahtever I want it
to mean
The semantics of the implicit argument used to initialize the
this pointer are the semantics of a reference, and the this
pointer behaves semantically like a reference: it cannot be
null, and it cannot be reseated. When asked why "this" is not
a reference, Stroustrup says "because references didn't exist
when it was introduced." In other words, if they had, this
would probably be a reference.


Allowed to do what? The standard is carefully crafted

Is it hell carefully crafted and neither are your invaLID ARGUMENTS.
GO **** yoursefl and your stupid arguments along with the rest of your
homosexual friends in the newsgroup.

Had enough of your unreasonable arguments , go just a fucking idiot after
all.

YOUR FUCKING WRONG1 why? BEcause I fuckin siad SO you IDIOT.
 
P

Paul

It means each function invokation is attached to a unique object

--What does this mean?

It means you are probably a bit stupid
bye I got more important things to do.
 
R

Rolf Magnus

James said:
The semantics of the implicit argument used to initialize the
this pointer are the semantics of a reference, and the this
pointer behaves semantically like a reference: it cannot be
null, and it cannot be reseated.

Syntactically and semantically, it behaves like a pointer that is constant.
And it cannot be null, because it's constant and always initialized with the
object's address.
The only point is that whether you write o.mthd() or mthd(o) is
purely syntax. (IIRC, Ada 95 chose the second form.) It has
nothing to do with what a function fundamentally is or is not.

In Python, you can use both, and the "this" pointer (or rather "self"
reference) is an explicit parameter usually called "self", but since it's
just a parameter, you can basically name it whatever you want. A static
member function is simly one that does not have the self parameter.
 
J

James Kanze

Syntactically and semantically, it behaves like a pointer that is constant.

No. It's not an lvalue. (You can't take its address, for
example.) It's a keyword, with a special meaning. Syntacticly,
a pointer (it has pointer type); semantically, more like
a reference; in reality, neither, but something special.
 
P

Paul

Rolf Magnus said:
The above code doesn't change the object, it changes the this-pointer.


Actually, I don't know what that code is supposed to tell me.


Not in a standard compliant way.


You should decide whether you want to look at it from the C++ standard
point
of view or from "behind the scenes". The heap, the stack and the concept
of
read only memory are not defined in C++. They are rather an implementation
detail. On that level, non-static member functions are implemented the
same
as non-member functions, but with the address of the object as a hidden
parameter.

Their whole argument is non standard, the basis of thier argument is that we
ignored the whole C++ syntax altogether and assume there is some other
syntax.
On the C++ level on the other hand, you have a pointer that is initially
declared const, and the C++ standard says that casting away constness of
such an object results in undefined behavior. So you cannot modify the
this-
pointer in a member function, and neither can you modify anObj in:
The fact that this is const actually supports the point I was making.


However I can't be arsed arguing with people who believe it is reasonable to
be non standard when it suits them yet any arguments against them must
always be in the context of the standards.
 
Ö

Öö Tiib

<snip headers>







--Yes, i understand. For me both the functions are part of A's
--interface:
--void A::eek:neOperation() {/* code operating on this */}
--void otherOperation( A& that ) {/* code operating on that */}

--What is the big matter if there is pointer "this" or reference "that"?
--The otherOperation() is even more OOP for me since it accesses only
--public interface of class A and does not mess with dirty inner
--details. So i know that if i for some performance reasons have to
--refactor implementation details of A leaving its public interface same
--then i don't need to modify otherOperation (or tests written for it).

Forgetting about operator oveloading , I am talking about what sort()
initially seemed to be proposed as, specifically:
anObj.sort(); /*A member function of anObject*/
sort(anObj) /*A normal function with 'this' passed explicitly as a
parameter*/

The difference is the possible sequences of execution given the following
scenario of recursion.

sort(){
    this = new anObjType; /*replace the object the function belongsto*/
    (*this).sort();  /*re-invoke this function is not possible, what does
'this' point to?*/
}

Does not compile. What compiles is:

void T::sort()
{
*this = T();
sort();
}

Why you brought it up? It is endless recursion that crashes when stack
is full.
sort(anObj){
    anObj = new anObjTye; /*replacing the object( heap or stack whatever,
the code is psuedo)*/
    pointertothisfunction(anObj) /*Ok to call this function, recursion is ok
with a new object.*/

}

Again does not compile. Compiles something like:

void sort( T& anObj )
{
anobj = T();
sort( anObj );
}

Still endless recursion.
The member function version does not have the same possible sequences of
execution as the normal version.
The member function version has an object identity, it belongs to the object
on which it is called.

I am maybe idiot or my English lacks but i can't parse what you say
here. The functions are equal for me only syntax of calling is
different.
 
P

Paul

<snip headers>







--Yes, i understand. For me both the functions are part of A's
--interface:
--void A::eek:neOperation() {/* code operating on this */}
--void otherOperation( A& that ) {/* code operating on that */}

--What is the big matter if there is pointer "this" or reference "that"?
--The otherOperation() is even more OOP for me since it accesses only
--public interface of class A and does not mess with dirty inner
--details. So i know that if i for some performance reasons have to
--refactor implementation details of A leaving its public interface same
--then i don't need to modify otherOperation (or tests written for it).

Forgetting about operator oveloading , I am talking about what sort()
initially seemed to be proposed as, specifically:
anObj.sort(); /*A member function of anObject*/
sort(anObj) /*A normal function with 'this' passed explicitly as a
parameter*/

The difference is the possible sequences of execution given the following
scenario of recursion.

sort(){
this = new anObjType; /*replace the object the function belongs to*/
(*this).sort(); /*re-invoke this function is not possible, what does
'this' point to?*/
}

--Does not compile. What compiles is:

It's not suppose to compile it was psuedo code, I repeat what I said in the
other thread:

An object is part of the calling process when we invoke a member
function.

One way to demonstrate this is to consider the difference between the
following two functions:
obj.membfunction();
ordinaryfunction(p_obj);

An ordinary function can be recursive with each recursion invoked with a
different object parameter:
void ordinaryfunction(T* p_obj){
call overwrite(p_obj ); /*asm subroutine to overwrite the object with a
new one in exactly the same region of memory. Dunno if it can be done in C++
*/
ordinaryfunction(p_obj); /*a new object for each recursion*/
}

The same cannot be done with a member function because the function belongs
to the object:
void memberfunction(){
call overwrite();
this->memberfunction() /*'this' is not modified but it points to a
different object */
/*ptr_to_thisfunction() Using a pointer to the opcode makes no
difference*/
}

The rules of C++ disallow member functions(instances of functions) to be
invoked with a different object thus .. the instance of the function belongs
to the object on which it was invoked.
Assuming you agree with above it follows that:
The sequence of execution for a member function is not always the same as
that of an ordinary function, for no other reason that the fact that the
function(or function invokation, if you need this directive) is a member of
an object.




--I am maybe idiot or my English lacks but i can't parse what you say
--here. The functions are equal for me only syntax of calling is
--different.

Please state what you don't understand about the above and I will clarify.
 
Ö

Öö Tiib

--Does not compile. What compiles is:

It's not suppose to compile it was psuedo code, I repeat what I said in the
other thread:

But lets agree that we from now on use for sake of simplicity real C++
code that compiles and no pseudo code.

struct T
{
void sort();
// other members
};

void T::sort()
{
// lot of code that involves
// re-assignment of value of object
*this = T();
// and recursive calls
sort();
}

void sort( T& that )
{
// lot of code that involves
// re-assignment of value of object
that = T();
// and recursive calls
sort( that );
}


Please state what you don't understand about the above and I will clarify..

What is so different about the two functions above (and please avoid
pseudo code that does not compile).
 
P

Paul

--Does not compile. What compiles is:

It's not suppose to compile it was psuedo code, I repeat what I said in
the
other thread:

--But lets agree that we from now on use for sake of simplicity real C++
--code that compiles and no pseudo code.

You can't do it with compileable code for a member function;
And for an ordinary function you would need to write an asm routine and
compile it to an obj file.

-- struct T { void sort(); // other members
--};

--void T::sort() {
-- *this = T();

What does the above code do?
invoke a copy constructor?
It doesn't replicate my code, to overwrite the object.

-- sort();
-- }

--void sort( T& that ) {
-- that = T();

Again what does this do?
Does it overwrite the old object? Why use type T , why not
that =Another Type()?

-- sort( that );

Why does your example not pass a pointer type, to replicate 'this' pointer?
'this' is simply a pointer stored in a register.
Your example places the constraint on the ordinary function, that it must
take a reference of the same type as the original object.
-- }

You have just demonstrated another reason why member functions are different
from ordinary functions:
An ordinary function can take any type of parameter. A member functions
'this' pointer cannot be type-casted.

Please state what you don't understand about the above and I will clarify.

--What is so different about the two functions above (and please avoid
--pseudo code that does not compile).

Your code does not replicate the same process as mine did.
 
Ö

Öö Tiib

--But lets agree that we from now on use for sake of simplicity real C++
--code that compiles and no pseudo code.

You can't do it with compileable code for a member function;
And for an ordinary function you would need to write an asm routine and
compile it to an obj file.

-- struct T {   void sort();     // other members
--};

 --void T::sort() {
--        *this = T();

What does the above code do?
invoke a copy constructor?
It doesn't replicate my code, to overwrite the object.

It does 3 things: dereferences this pointer, default constructs
temporary object of type T and copy-assigns the constructed temporary
objects value to dereferenced this object overwriting its contents
(unless there is user-defined copy-assignment operator that does
something else). I am not sure how this code does not overwrite the
object by your school of philosophy. :-/
--         sort();
-- }

 --void sort( T& that ) {
-- that = T();

Again what does this do?
Does it overwrite the old object? Why use type T , why not
that =Another Type()?

It does exactly same thing like first code, only that since "that" is
passed by reference it is already dereferenced.
 --     sort( that );

Why does your example not pass a pointer type, to replicate 'this' pointer?
'this' is simply a pointer stored in a register.

Because "this" can not be NULL nor modified and so reference is
behaving more similarly.
Your example places the constraint on the ordinary function, that it must
take a reference of the same type as the original object.

Please elaborate. I can not parse what that constraint is. I pass most
of the non-fundamental parameters by reference in my code. Passing by
value involves copying and passing with pointer makes it optional, so
i have to check that pointer for NULLness inside function. In C++ when
i have function with optional parameter i prefer using an overload of
function that lacks the parameter instead of making it pointer. In C
language there are no references nor overloads so there i use
pointers.
-- }

You have just demonstrated another reason why member functions are different
from ordinary functions:
An ordinary function can take any type of parameter. A member functions
'this' pointer cannot be type-casted.

It was that people argued with you that ordinary function can behave
like a member function. It has to have parameters that fit with that
task? You may cast pointer returned by keyword "this" in member
function to something else, but i don't understand what it has to do
with our discussion.
--What is so different about the two functions above (and please avoid
--pseudo code that does not compile).

Your code does not replicate the same process as mine did.

That is perhaps because i did not understand what your pseudo-code was
doing. Please explain or write in C++, then i likely understand it
better.
 
P

Paul

--But lets agree that we from now on use for sake of simplicity real C++
--code that compiles and no pseudo code.

You can't do it with compileable code for a member function;
And for an ordinary function you would need to write an asm routine and
compile it to an obj file.

-- struct T { void sort(); // other members
--};

--void T::sort() {
-- *this = T();

What does the above code do?
invoke a copy constructor?
It doesn't replicate my code, to overwrite the object.

--It does 3 things: dereferences this pointer, default constructs
--temporary object of type T and copy-assigns the constructed temporary
--objects value to dereferenced this object overwriting its contents
--(unless there is user-defined copy-assignment operator that does
--something else). I am not sure how this code does not overwrite the
--object by your school of philosophy. :-/


You do know the differnece , think about it:
If there were two objects types Cat and Dog, for completeness lets say the
both implement base class Animal.
Cat cat
Dog dog;
dog = Dog(); /*This is equivalent to your code.* /
overwrite(p_dog, p_cat); /*My code trully overwrites the object, it doesn't
just change a few values.*/

The term overwrite could mean for example...overwrite with a completely new
data structure.

-- sort();
-- }

--void sort( T& that ) {
-- that = T();

Again what does this do?
Does it overwrite the old object? Why use type T , why not
that =Another Type()?

--It does exactly same thing like first code, only that since "that" is
--passed by reference it is already dereferenced.

Then see my comments on the first code.
Assigning values to an object is not the same as overwriting its memory IMO.
-- sort( that );

Why does your example not pass a pointer type, to replicate 'this'
pointer?
'this' is simply a pointer stored in a register.

--Because "this" can not be NULL nor modified and so reference is
--behaving more similarly.

'this' can be modified and so can the object it points to.
Remember for example, thiscall uses ECX, ECX is not a read only register so
how can I not modify the 'this' pointer. However this is irrelllevant
because I don't need to modify the 'this' pointer to change the object it
points too.
Your example places the constraint on the ordinary function, that it must
take a reference of the same type as the original object.

--Please elaborate.

I have elaborated enough for you to understand now.
I need to go out, so I'm snipping the rest.


Please let me know if you still do not understand and I will re-explain
again.
 
Ö

Öö Tiib

Please let me know if you still do not understand and I will re-explain
again.

Your code does not work. You can not overwrite object 'Dog dog;' in a
way that Cat's destructor is called for it when that dog leaves
scope ... Dog's destructor is called for it on all C++ compilers i
could reach. What destructor will be called is pre-decided and set
already compile time. So it seems that you do not understand yourself
what you are talking about.
 
P

Paul

Please let me know if you still do not understand and I will re-explain
again.

--Your code does not work. You can not overwrite object 'Dog dog;' in a
--way that Cat's destructor is called for it when that dog leaves
--scope ... Dog's destructor is called for it on all C++ compilers i
--could reach. What destructor will be called is pre-decided and set
--already compile time. So it seems that you do not understand yourself
--what you are talking about.

#include <iostream>
class Animal{};
class Dog: public Animal{};
class Cat: public Animal{};

int main()
{
Cat* p_cat = new Cat;
std::cout<< p_cat << std::endl;
delete p_cat;
Dog* p_dog = reinterpret_cast<Dog*>(p_cat);
p_dog = new Dog;
std::cout << p_dog;
}
 
Ö

Öö Tiib

--Your code does not work. You can not overwrite object 'Dog dog;' in a
--way that Cat's destructor is called for it when that dog leaves
--scope ... Dog's destructor is called for it on all C++ compilers i
--could reach. What destructor will be called is pre-decided and set
--already compile time. So it seems that you do not understand yourself
--what you are talking about.

#include <iostream>
class Animal{};
class Dog: public Animal{};
class Cat: public Animal{};

int main()
{
 Cat* p_cat = new Cat;
 std::cout<< p_cat << std::endl;
 delete p_cat;
 Dog* p_dog = reinterpret_cast<Dog*>(p_cat);
 p_dog = new Dog;
 std::cout << p_dog;



}

What does this code overwrite?
Also ... most compilers optimize the two lines:

 Dog* p_dog = reinterpret_cast<Dog*>(p_cat);
 p_dog = new Dog;

Into something like:

 Dog* p_dog = new Dog;
 
P

Paul

--Your code does not work. You can not overwrite object 'Dog dog;' in a
--way that Cat's destructor is called for it when that dog leaves
--scope ... Dog's destructor is called for it on all C++ compilers i
--could reach. What destructor will be called is pre-decided and set
--already compile time. So it seems that you do not understand yourself
--what you are talking about.

#include <iostream>
class Animal{};
class Dog: public Animal{};
class Cat: public Animal{};

int main()
{
Cat* p_cat = new Cat;
std::cout<< p_cat << std::endl;
delete p_cat;
Dog* p_dog = reinterpret_cast<Dog*>(p_cat);
p_dog = new Dog;
std::cout << p_dog;



}

--What does this code overwrite?
--Also ... most compilers optimize the two lines:

--Dog* p_dog = reinterpret_cast<Dog*>(p_cat);
--p_dog = new Dog;

--Into something like:

-- Dog* p_dog = new Dog;

It doesn't trully overwrite anything but its the closet example I can give,
using C++ code.

Here is some code that demonstrates a similar thing:

#include <iostream>
class Animal{public:
virtual void eat(){std::cout<< "Animal Eating"<< std::endl;}
virtual int getID()=0;
static int count;
};
class Dog: public Animal{
public:
void eat(){std::cout<< "Dog Eating"<< std::endl;}
int getID(){return 1;}
};
class Cat: public Animal{
public:
void eat(){std::cout<< "Cat Eating"<< std::endl;}
int getID(){return 0;}
};
int Animal::count =10;

Dog* overwriteCat(Animal* ptr){
delete ptr;
Dog* p = reinterpret_cast<Dog*>(ptr);
p = new Dog;
return p;
}

Cat* overwriteDog(Animal* ptr){
delete ptr;
Cat* p = reinterpret_cast<Cat*>(ptr);
p = new Cat;
return p;
}


void ordinary_function(Animal* obj){
Animal::count--;
std::cout<<"Address of obj: " <<obj << " ";
obj->eat();
if(obj->getID()){overwriteDog(obj);}
else {overwriteCat(obj);}
if(Animal::count){
ordinary_function(obj);
}
}

int main()
{
Cat* p_cat = new Cat;
Animal* p_anim = p_cat;

ordinary_function(p_cat);
}


You cannot do this type of recursion with a member function, a member
function belongs to the object with which its called.
 
P

Paul

Leigh Johnston said:
In C++ a member function does not belong to a particular object; in C++ a
non-static member function is invoked on an object; in C++ a member
function is a member of a class not an object.

If its a member of the class its also a member of the object you f*#"&i%$
moron.
If its a member of a class and not a member of an object it can only be a
static class member.

Please keep your ignorant, negative , spamming comments to yourself if you
have no reasoning to support your argument.
 

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,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top