I'm sorry, it's been a while since I posted that post....
Don't really remember why I wrote that, and I don't see the logic in why I did that since you've allready wrote the same type of code and you said the the instance goes to the stack in that way.
So, I belive I made a mistake and wanted to ask what happens when I write:
Code:
MyClass InstanceonWHO = new MyClass();
Compile error, new MyClass(); returns an int, the pointer to the object in memory. So it is an invalid conversion from int to MyClass. This is also where the dereferencing (*) and member by pointer (->) operators start to make sense.
You can only call methods and edit fields from an actual object, remember pointers are just locations. So to operate on a pointer to an object one uses the member by pointer operator:
Code:
myInstance->myMethod();
which dereferences the pointer, returning the actual object, and then calls the method, which is equivalent to the following:
Code:
(*myInstance).myMethod();
This is how stl iterators work, where the beginning and end locations of objects in the collection are stored in the container, so one can compare those to the iterators actual value to see if you are at the beginning or end; then if one dereferences the iterator one gets the object that is being pointed to.
Disclaimer: I wrote this at 2:00am, actually hey look it's 1 again, yay time change, so forgive me if there is some incoherence.
Because of polymorphism, where pointers from inherited classes are type-compatible with their base class. This is useful when you have multiple objects that use an object from a base class; since they're all inherited they can use an object from a base class, as well as use whatever specific objects from their own class.
Thanks for the postings guys (and thanks to all the other teams that posted their code). This should give teams a nice little preview and head start on how to program the new control system.
Compliers are NOT created equally! Some compilers will initialize all your points to null for you automatically and also resets them to null after you delete the object, some compilers don’t. What happens if they don’t is that when a pointer is created it ends up pointing to some random (not null) memory location.
Why it matters:
If your program starts to run and you forgot to create a new object but attempt to access a method for the object via the pointer one of two things will happen depending on if the pointer was initialized or not. If the pointer was initialized by the compiler (or by you) then your program will crash immediately and the stack trace will be on the line and you will be able to tell that your pointer was null and can easily correct the issue. If the pointer points to a random memory address, you program will continue for a while but your results will be unpredictable, and when your program does finally crash, the stack trace will be very hard to follow and finding the really issue will be very time consuming.
So my suggestion is to always initialize your pointers and reset them to null after deleting them. Note that some compilers have NULL or null defined for you, some don’t. If yours doesn’t null is the same as 0 (zero). Here is the code to do that:
// Initialize to null
MyClass * myInstance = NULL;
...
// Make sure someone else didn’t delete your instance
if (myInstance != NULL)
{
delete myInstance;
// reset to null
myInstance = NULL;
}
__________________________________________
You can check to see what the compiler supports, but the above are good habits to get into. Here is the code to check your compiler.
// not initialize by the programmer, could be by the compiler
MyClass * myInstance;
// test what the compiler does on declaring a pointer
if ( myInstance == NULL )
cout << “Good compiler” << endl;
else
cout << “Bad compiler” << endl;
// now test what the compiler does on delete
myInstance = new MyClass;
delete myInstance;
Here is Team 67's updated version of the original code posted in this thread that we presented at the Novi, Michigan FRC Kickoff. Additions to the original code include:
- updated drive and arm motors to jaguars
- sends data to the dashboard including the standard default dashboard information, images from the Axis camera, autonomous program number selection, and printf diagnostic output.
- my own copy of TrackAPI that includes fixes for bugs I found. These fixes are not yet in the released version of WPILib -- they should be soon. Use at your own risk: Team 67 will not be responsible for shingles, pain in the joints or halitosis incurred from using this code.
Five autonomous programs of increasing complexity:
0. Display output from encoders and gyro on the dashboard and console.
1. Drive straight using a gyro for control.
2. Drive a specified distance using encoders.
3. Drive in a zig-zag pattern using gyro and encoders.
4. Simple 2007 Rack 'n Roll without the Rack: Raise the arm, search for the green light, drive to the light, lower the arm.
Dave D
FRC: HOT, Team 67, Mentor, C++ Beta Test Lead
FLL: Dark Matter Dark Energy, Team 3069, Coach
And don't forget to set pointers to NULL when you delete them!
Code:
Robot* r = new Robot();
/* Code Ommited */
delete r;
Button btn = new Button();
r = new Robot(); // BAD!
if(btn->isPressed()) // Likely cause the program to crash
...