No. You must include <stdio.h> or define it yourself (to be 0) with #define.
A void pointer. Think of it as a pointer to a generic Object. If you wish to access a specific member function or variable of an object that is being pointed to by void *, you must cast first.
No. Only if you intend on making a class do you need a .h file. (So dllist-driver.cc doesn't need a .h file.)
That's the scope operator. You use that to indicate that a function belongs in a certain class. For example, the RemoveHead() method belongs in your DLList class, so the full prototype will be:
void *DLList::RemoveHead(int *sortKey)
Note that the return type (void *) goes before the DLList. Think of DLList::RemoveHead as the "full name" of the function ("function RemoveHead of the DLList class") so the return type (void *) precedes it.
If file <A> has a line "#include <B>" in it, the compiler literally takes the contents of <B> and appends it to the code in <A>. So if you accidentally #include the same file twice (say, with the same #include stmt in 2 different files), you'll accidentally end up with duplicate definitions of things. And the compiler will complain. #ifndef ("if not defined") prevents this. By encapsulating the contents of a *.h file in an #ifndef block, you only define it anew if it hasn't already been defined. So in DLList.h, I have:
#ifndef DLLIST_H #define DLLIST_H ...rest of DLList.h file #endifwhich means I'm defining the DLLIST_H block to be the entire contents of the DLList.h file. And the preceding #ifndef means don't define this if it is already defined. Bottom line: It is good practice in any .h file to enclose all the code in a #ifndef block.
Two options here. (1) Use extern stmts to tell the file that is calling AddN that there are external functions that are available. The extern command lists the prototype of the external function. So in dllist-nachostest.cc, for example, you would have a statement like
extern void AddN(DLList *list, int n);
These statements normally go at the top of the file, after the #include statements, if any. Option (2) is: make the file in which AddN is defined (dllist-driver.cc in this example) into a class. That is, create a dllist.driver.h file and add it to the make file.
Yes you can. In Java these are primitives, but C makes no such distinction. You can say:
char *c = new char();
and c will now be a pointer to a char.
DLList myList = new DLList();
This gives me a pointer (named myList) to a new DLList object. How do I do the equivalent in C++?
You would do the following:
DLList *myList = new DLList();
This makes myList a pointer to a new DLList. So now you can access member functions with the arrow (->). For example:
char *c = new char(); *c = 'A'; myList->Prepend(c);
Suppose you have a pointer p pointing to a DLLElement, and you want to print the character pointed to by its data field. Here's the command:
printf("%c", *((char *)p->data));
Let's break this down:
This is an example of where good code design is being sacrificed. This code only works if you know the DLList is only going to hold chars. Don't worry about it. I want you focusing on the OS-related concepts of this course, so there will be times (quite a few actually) where we won't worry about your code's generality.
That's a deconstructor, sometimes called a destructor. Unlike Java, which has automatic garbage collection routines, C++ has no such thing. You must explicitly delete objects when you are done using them. Not doing so will just let those unused objects collect in memory, and the amount of available memory will decrease -- that's what a memory leak is.
For this project, you should loop through the linked list and explicitly delete each node with the "delete" command. Just setting first and last to null won't put the memory used by the nodes back on the heap.
The "delete" command is also used to call the destructor. So if you did:
DLList *list = new DLList();
will call the destructor. Rule of thumb: for every object you create with new, you should have a corresponding delete of that object somewhere in your code.