14 May, 2009, JohnnyStarr wrote in the 1st comment:
Votes: 0
Ok,
I know i've started a ton of threads with questions about C and C++, so i thought i might save
the forum some sql records and create a thread about the questions i have as they come up.

QUESTION: 1

I probably made the mistake of learning C before i messed with C++, so i'm having a hard time wrapping
my brain around the purpose of creating a pointer to a class?

I took this from www.cplusplus.com

// pointer to classes example
#include <iostream>
using namespace std;

class CRectangle {
int width, height;
public:
void set_values (int, int);
int area (void) {return (width * height);}
};

void CRectangle::set_values (int a, int b) {
width = a;
height = b;
}

int main () {
CRectangle a, *b, *c;
CRectangle * d = new CRectangle[2];
b= new CRectangle;
c= &a;
a.set_values (1,2);
b->set_values (3,4);
d->set_values (5,6);
d[1].set_values (7,8);
cout << "a area: " << a.area() << endl;
cout << "*b area: " << b->area() << endl;
cout << "*c area: " << c->area() << endl;
cout << "d[0] area: " << d[0].area() << endl;
cout << "d[1] area: " << d[1].area() << endl;
delete[] d;
delete b;
return 0;
}


Could someone explain the difference or need of using a pointer instead of just using the object?
14 May, 2009, ghasatta wrote in the 2nd comment:
Votes: 0
Here's a link I found on the google: http://www.embedded.com/story/OEG2001031...

This isn't really an issue that came about with C++ - plain old C can make heavy use of pointers as well (and remember of course thatstructs and classes are more or less the...).

Functionally, pointers and references (or 'just using the object') can all be used to access the members of the class. However, since a pointer contains the memory address of something (a class object in this case), it is also a convenient way to pass an object around (to store it in a list, pass to a function so that the function can call its methods, etc). Pointers can be NULL whereas references can't be, pointers can be reassigned, etc.

Memory management is also a factor - objects created with the 'new' operator don't get destroyed until you explicitly invoke the 'delete' operator, whereas objects created on the stack will of course be invalidated once they go out of scope.

From your posts I get the impression that you are comfortable with programming terms so I am going to just throw these thoughts out there and trust you to post back if you need more clarification of anything ;)

HTH.
14 May, 2009, JohnnyStarr wrote in the 3rd comment:
Votes: 0
Thanks for the post,

So if I understood correctly, you can use a reference to an object, but if you use a pointer to a class object,
you have more ability over perhaps using pointer arithmetic and memory management?

I might point out that my OOP understanding is more from a Ruby perspective, if that helps.
14 May, 2009, elanthis wrote in the 4th comment:
Votes: 0
staryavsky said:
I probably made the mistake of learning C before i messed with C++


Not a mistake at all. I refuse to teach people anything about C++ before they learn C. It can take a little backtracking to understand C++ if you start with C, but every person I've ever met who learned C++ first ended up having a hell of time understanding C, and you can't actually truly understand C++ without having a solid grasp on C and its various low-level fundamental concepts. So you did the right thing. :)

Quote
my brain around the purpose of creating a pointer to a class?


Technically, a pointer to an instance of a class. :)

It's no different than creating a pointer to a struct. An object (instance of a class) by itself is a big blob of data. If you pass the object itself around, you are actually passing by value – that is, you are copying the object and all of its contents. Using a pointer lets you pass around the address of the object instead.

As an example:

#include <iostream>

using namespace std;

class Foo {
public:
int bar;
};

void increment_copy(Foo object) {
object.bar ++;
}

void increment_pointer(Foo* object) {
object.bar ++;
}

int main() {
Foo object;
object.bar = 7;

cout << object.bar << endl;
increment_copy(object);
cout << object.bar << endl;
increment_pointer(&object);
cout << object.bar << endl;

return 0;
}


That will print out:

7
7
8

The first increment (not using a pointer) doesn't appear to do anything. That's because a copy of the Foo object is passed in, the bar member of the copy is incremented, and Foo object in main is untouched. The second increment (using the pointer) updates the Foo object in main because it is passed a pointer to the instance and directly modifies that object.

C++ also has references, which are probably the most confusing thing to grok when coming from a C background. In many ways references just seem like a synonym for pointers… which, under the hood, they are. In the language itself though they have a few differences. Basically, a reference (e.g. Foo& object) must be initialized, and assigning to a reference calls the assignment operator on the object itself but does not change which object is referenced, while a pointer (e.g. Foo* object) does not have to be initialized, and assigning to a pointer changes which object it points to. They were added to C++ mostly for the sake of operator overloading, but they're used all over the place in most C++ apps now either for out parameters (where you'd just use a pointer in C) or for performance (again, where you'd just use a pointer in C).
14 May, 2009, JohnnyStarr wrote in the 5th comment:
Votes: 0
Ok…
I'm starting to see what seems to be duality in C++'s nature.
But thank you, I'm starting to see how that makes sense.
I guess you could compare C++ to English in the way that it has a ton of weird rules that
sort of make sense, but at the same time it doesn't appear logical.

disclaimer: I don't in anyway claim that what I'm stating above is anything but my humble
ignorant opinion. feel free to point me in the right direction if am mistaken.
14 May, 2009, David Haley wrote in the 6th comment:
Votes: 0
Most of these concepts exist in most programming languages already. In Ruby, if you pass an object to a function, you're not passing around a whole copy of the object: if the function does something to the object (such as, say, telling it to change color) the object itself is changed, not the copy of the object.

Whereas Ruby/Python/Lua etc. don't really give you the choice of passing parameters by reference or by value, C and C++ do give you this option. (This is a little confusing here because I'm not using "reference" to mean C++ reference – please bear with me.) As others have said, if you pass a struct to a function as-is, you're copying the whole chunk of memory. This can be undesirable for at least two reasons:
1. if the function wants to modify the parameter, it has to return it back to the caller. This can be cumbersome when several objects are being modified at once.
2. copying whole structures is inefficient, all the more so as objects get larger

A pointer is literally just a memory address. Conceptually, it's like a handle to something, a way to find something if you will. You have this chunk floating around in memory; a pointer lets you find it. You can pass the chunk around as-is (on the stack, technically speaking) or by telling other people how to find it. It's not just that pointers are for pointer arithmetic; pointer arithmetic exists only because of the fact that pointers in C really are just memory locations.

Frankly I've always found that a lot of this makes a lot more sense as you draw out memory diagrams showing what's on the stack, what's on the heap, and what points where. I need to cut this short now unfortunately, but maybe later I can write more.
14 May, 2009, David Haley wrote in the 7th comment:
Votes: 0
Quote
I guess you could compare C++ to English in the way that it has a ton of weird rules that
sort of make sense, but at the same time it doesn't appear logical.

Well, actually the rules are completely coherent and aren't really like English at all. It's not a big mystery thing that works in weird ways; there really is a pretty clear way of how things work.
14 May, 2009, JohnnyStarr wrote in the 8th comment:
Votes: 0
Ok, thanks for the clarifaction as well David.

Here's where i check in to make sure i'm actually understanding:
So, i do understand the purpose for passing around a memory address instead of the
actual object. I do understand the value of having it temporarly stored on the stack as well.

What i was trying to understand is this; does languages that do not use pointers, such as Ruby,
pass the equivalent of a 'pointer' when you this for example:

class Name_changer

def change_name(player)
player.change_name_to("Johnny Starr")
end

end

j = Player.new

n = Name_changer.new

n.change_name( j )


ok, i totally wrote this in like 5 seconds so yes, its probably not the best example, but what i'm trying
to point out is that when i passed ' j ' into the name_changer, was that actually passing the object, or the
refference? or is it like comparing apples and oranges?
14 May, 2009, David Haley wrote in the 9th comment:
Votes: 0
That's what I was referring to – languages like Ruby/Python implicitly pass objects by reference. You have no choice really but to pass it by reference: you could pass in a copy, but then you'd just be creating the copy on the caller side, and passing in a reference to the copy…
14 May, 2009, JohnnyStarr wrote in the 10th comment:
Votes: 0
Ok, coolness, i get it.

Now, the other side of my question is this:
Using Enathis' example above of the increment thing, would there ever be any
benefit to explicitly using just a bare 'blob' of the object refference itself?
Or is it just good to always use pointers to objects?

I mean, as David pointed out there is a reason for everything. Why give us as programmers
the option to do both?
14 May, 2009, David Haley wrote in the 11th comment:
Votes: 0
Well, sometimes you want to give some structure to a function and it will mess with it, but you don't want it to mess with the caller's copy. So you can either pass in a copy, or you can pass in a pointer and have the function make a copy itself (at which point you might as well pass in a copy).

In practice, most of my code passes around constant references (which is nice syntactically on the caller side, but keeps efficiency, while preserving the inability of the callee to modify the caller's data), pointers, or primitives (int, double, …) passed as-is. It is relatively rare that I pass around copies of objects: if I don't need to modify them, I pass them as constant references; if I do need to modify them, I pass them as references or as pointers.
14 May, 2009, JohnnyStarr wrote in the 12th comment:
Votes: 0
David said:
Quote
It is relatively rare that I pass around copies of objects: if I don't need to modify them, I pass them as constant references; if I do need to modify them, I pass them as references or as pointers.


So a "constant" reference might be a list of something like the "skill table"
or "race list" or other things.

But something that can change like "character list" or "inventory" you would
pass the pointer?

If so that totally makes sense.
14 May, 2009, David Haley wrote in the 13th comment:
Votes: 0
Well… not always. But those are examples. Typically things like the skill table and race list would never change, so there's no reason to pass them around as non-constants. But that's kind of a separate issue from pointer vs. reference. Pointers vs. references in C++ is really a syntactic thing, allowing among other things very convenient operator overloading as Elanthis referred to earlier. (Objects can return references to themselves, thus allowing you to continue applying operators.)

The most important concept to understand is not reference vs. pointer, it is on-the-stack vs. on-the-heap, or if you will, non-reference vs. "reference" (where "reference" here means handle-to, not a literal C++-style reference – i.e. C++ reference or pointer).
15 May, 2009, elanthis wrote in the 14th comment:
Votes: 0
Silly C++ terminology. I understand it all and I'm still getting confused by this thread. ;)

The terminology here is complex because "reference" means different things in different languages, separate from what it means in general computer science. In most dynamic languages like Ruby or Lua, everything is passed "by reference" which means that the objects aren't copied. A variable doesn't have "an object" but instead has a "reference to an object."

Some dynamic languages like PHP however has an actual "reference" type that means you are passing a reference _to a variable_ and has nothing to do with the object model in question. That is, in PHP, if you pass a reference to a function which then changes the reference, the calling method will see a different object in the variable it passed to the function.

C and C++, unlike Ruby, pass by value and not by reference. If you want to give a reference to an object to a function, you need to use a pointer and give it the memory address of the object. The C++ reference type is a strange and mysterious beast, though.

In a way, it's similar to PHP in that you are passing a reference to a specific variable and not an object. However, unlike PHP, assigning to a reference does not change which object the variable refers to! It copies the source object into the target object, just like you were using non-pointer variables. The whole C++ reference type thing exists only because of the strictness of the type system – Foo and Foo* are two separate types and you cannot directly assign between them, which means that using raw pointer you have to explicitly pass in the address to an object to a function that wants a reference. For the purpose of operator overloading and a few other C++ features, that would result in very weird-looking code and it would conflict with basic pointer arithmetic, so they added the C++ reference stuff (because you can directly assign Foo to a Foo& variable/parameter, unlike a pointer parameter that would require an explicit & operator to get the address). It's one of the uglier warts in C++, although to be fair, I can't come up with any better solution that solves all issues in question.

To simplify things, you really only have one thing to keep in mind: do you want to pass around a copy of an object or a reference to the object. In the former case, just pass the object directly (e.g., parameter of type Foo) and in the latter case, just use a pointer (e.g., parameter of type Foo*). The C++ reference type is something you can safely avoid entirely in a lot of cases, as its only really mandatory in a small handful of more advanced use cases, and the only thing it offers otherwise is a little cleaner looking code for another handful of specialized cases.

One thing you will see a lot in C++ code that I will point out is the use of const std::string& parameters. That is entirely a performance thing. In C++, unlike Ruby or most other scripting languages, the standard string type is mutable. Because of that, assigning a std::string creates a copy of the string. Which is slow. So it's faster to pass a reference to a string, which is basically exactly what you're doing when you pass a char* in a C function, except that the C++ string can handle resizing and stuff unlike a basic C string. You make the reference const just to make it clear that it's not an OUT parameter and that you don't want the method to modify your copy of the string.
15 May, 2009, David Haley wrote in the 15th comment:
Votes: 0
elanthis said:
C and C++, unlike Ruby, pass by value and not by reference. If you want to give a reference to an object to a function, you need to use a pointer and give it the memory address of the object.

What's interesting about this is that although passing a pointer means passing the thing pointed to by reference, you're passing the pointer by value. If you want to change what the pointer points to, as opposed to changing the thing the pointer points to, you need to pass the pointer itself by reference, meaning passing a pointer to a pointer…

(that is usually the part where new C/C++ students' heads explode)

elanthis said:
It's one of the uglier warts in C++, although to be fair, I can't come up with any better solution that solves all issues in question.

I don't have the link around, but I read that several people have tried to redesign C++ but wanting to do it "correctly", while respecting the initial design goals. It turns out that it's extremely difficult to make a new language that respects C++'s goals without ending up with pretty much exactly C++ all over again. (The goals being things like C programs should also be C++ programs, there should be no cost if you don't use C++ features, etc.)
15 May, 2009, JohnnyStarr wrote in the 16th comment:
Votes: 0
So David, i know that you're site says that BabbleMud is completly redesigned in C++.

You know how C has all sorts of handler functions and such? I'm curious what a C++ MUD
would look like if done correctly. It's kind of weird that for all the muds that are out there, there
are none that i can find that are in C++ that are written with a good object oriented structure.

Most of anything that i know of was a mud that started in C and had C++ functionality added
after the fact.

Mind you, the only reason i would do a mud in C++ would be to not have to rewrite code, so
that would mean i could class objects and have some encapsulation, but that in itself is allot of
work. May i ask, why you chose to write a stock mud in C++ when you could have used an
interpreted language that it seems to me at least, you really think are the way of the future and love?

I know it says you use Lua in your mud, so maybe thats why.
15 May, 2009, David Haley wrote in the 17th comment:
Votes: 0
Quote
You know how C has all sorts of handler functions and such?

Actually no, I'm not really sure what you're talking about here… Are you talking about something in the language itself, or something in C MUD codebases?

Quote
It's kind of weird that for all the muds that are out there, there are none that i can find that are in C++ that are written with a good object oriented structure.

This is mainly due to the fact that for whatever reason (I have my theories but they're not relevant right now), MUD developers tend to write in C, not C++. There are very few codebases in C++ to begin with, let alone codebases that were designed to be object oriented.

That said, C can be object oriented just like C++ can, it's just that C++ enforces it. A method is really nothing more than a function that takes the object as its first parameter. You'd have to implement things like polymorphism yourself – where a function behaves differently depending on the type of the object passed in – but you can do it. C++ just makes it easier.

You can always encapsulate code in C, you just have to be strict with yourself to not violate interface constraints. A lot of new coders don't realize that there are such things as "interface constraints" and start manipulating structure variables directly, causing havoc when done inappropriately.

Quote
May i ask, why you chose to write a stock mud in C++ when you could have used an
interpreted language that it seems to me at least, you really think are the way of the future and love?

I know it says you use Lua in your mud, so maybe thats why.

I'm not sure I understand your question of why I use only C++ given that just below you say I use Lua. :tongue:

For what it's worth, as I think about this and write more prototype code, I'm finding that I want/need less and less in C++ – maybe even nothing, at some point.
15 May, 2009, JohnnyStarr wrote in the 18th comment:
Votes: 0
Yeah, I meant handler.c in Diku based muds. Sorry, for some reason i assume everyone can read my thoughts apparently. :redface:

Thats really cool that C can be used that way, now that i think about it, it makes sense.

Also, about C++ and Lua, i meant to ask rather what you answered in your last post, which is why would you need C++ at all? I know Lua is meant to be embedded, but as we discussed before with the advent of faster computers and systems, there really isn't a "need" for the same speed that C++ might avail.
15 May, 2009, David Haley wrote in the 19th comment:
Votes: 0
A lot of people fail to understand that object orientation isn't really a language "feature", it's a method of programming. You can write object oriented programs in languages that were invented before object orientation was… It's just that languages that were designed with OOP in mind will make it easier to do so.

And yes, I'm not sure there's really a need for C++ speed, although that's pure conjecture: I've not actually benchmarked a full Lua MUD with active players, mobs running around doing stuff, and so forth, mainly because I don't have a full Lua MUD to do so. :wink: I suspect that depending on what you're doing, it could make sense to have some things in C++ such as figuring out which entities need to be updated or run their AI routines, but then have the actual AI routines be implemented in Lua. Again, though, it's quite possible that Lua alone would be fast enough for this.

I am slightly skeptical of using Lua to implement the network routines because that involves shuffling around bytes at a fairly granular level, doing transformations on byte streams, and so forth. You definitely don't want to construct strings one character at a time in Lua, although having an array of bytes might very well suffice in terms of performance.
15 May, 2009, JohnnyStarr wrote in the 20th comment:
Votes: 0
David, i have another question.

when you are talking about the 'interface', i'm pretty certain you
are speaking of the concept of a class objects interface to other
objects or calls from functions. in other words, the interface contraints
would be how you write your code to access classes members.

so it would be bad form to do this:

player.level = player.level + 1;


instead you would do something like this:

player.level_up()


the above would call an encapsulated method that would internally
alter the 'level' member.

Now, if i'm on the right track, is that what you mean by interface? because i know that in C# interface is a built in feature, and i've read C++ dosn't have that.
0.0/72