class Object { public: Object(); //Set up acceptable defaults, alloc mem ~Object(); //Deallocate memory if any was reserved
void Init();//Sends unique data for this instance
bool Update();//returns true if the object needs to be killed void Draw();//If graphical, displays itself to user
void Save(int file);//Pass a file descriptor and save void Load(int file);//Read Init() info from a file private: //Object data would go here };
pointer should intuitively follow this approach:
MyClass* classPtr; classPtr = new MyClass();
As with other variables, all of the same rules apply, the ampersand (&) to get the address, and the leading asterisk (*) to reach the actual data.
But what of the dot operator (.)? The dot operator requires data on the left side in order to access a function/variable in the class. You could do it this way:
(*classPtr).someFunction(); (*classPtr).someVariable = 15;
This statement works, but requires more typing. Luckily there is a shortcut for this, using the indirection operator (->). This operator works on a pointer to a class just like the dot operator. Note that if you use it to access a variable it returns the data of that variable and not a pointer to it:
classPtr->someFunction(); //Same as statements above classPtr->someVariable = 15;
-5- There are good examples for using "class" to do the "data structure" --
class BaseClass { public: void doStuff(); int data; };
class DervClass : public BaseClass { public: void doStuff(); int moreData; };
void main() { DervClass obj1; BaseClass obj2; BaseClass* ptr1 = &obj1; //Assigning an DervClass to a BaseClass pointer! }
This can seem pretty extreme, but if you think about it, this is totally workable. On a BaseClass*, you can use all of the functions available in BaseClass, which work on BaseClass variables. These functions and variables also exist in DervClass, being a class derived from BaseClass, and so the same things should work. This is because DervClass is really a "BaseClass and then some," and you can always in a sense "downgrade" your status.
When you call methods or access variables from the pointers, everything works as normal except for the fact that when you use the base pointer, you can only access things from the base class. For example, given a continuation of main() from above:
ptr1->doStuff(); //Calls BaseClass::doStuff(), NOT DervClass:dostuff()! ptr1->moreData = 5; // NOT valid since moreData is in DervClass, and //this is a BaseClass* ptr1->data = 10; //Valid statement
In the next few lessons you will see how to overcome the problem presented by the last code, where the BaseClass::doStuff() was called when you probably wanted to call DervClass::doStuff().
The reserved word virtual is the main concept presented by this code. On methods besides the destructor, this means that the method can be overridden by an inherited class when the method is called on the base pointer. This can sound confusing at first since the previous lessons have already shown this is possible. But with virtual functions the point is that you do not need to know which class it came from! Observe the following code:
//The usual way: Person man("Bob", 35, "15th S Pine St"); Student woman("Jill", 19, "n/a -- dormatory", "RIT"); man.display(); //This is valid, called Person::display() woman.display(); //calls Student::display() //With virtual methods: Person* baseptr = man; baseptr->display(); //calls Person::display() baseptr = woman; //Can assign Student* to Person* baseptr->display(); //Calls Student::display();
Using the virtual keyword we overcame the problem we had in the first lesson for this chapter. Even when the pointer loses its identity we can still override functions in the derived class. Note that even still, the method must exist in the base class in order to call it -- it is just simply virtual says it should look to see if there is an override.
--
No comments:
Post a Comment