lecture 03a: c++ classes topics: basic classes and objects constructor, destructor miscellaney an...
TRANSCRIPT
Lecture 03a: C++ classes
Topics:• basic classes and objects• constructor, destructor• Miscellaney• An intro to the STL (Standard Template Library)
Overview
• A way to combine– Data (attributes, or member variables)• We had this in struct’s
– Behaviors (methods, or member functions)• We didn’t have this in struct’s
• Very natural way to program…– …for some people– …after you get past the learning curve
Part I: Basic Classes and Objects
• Two parts:– Class design
• Not necessary if using someone else's class (e.g. SDL)• Designing a blueprint for a new type
– Make instances (objects) of a class• Each shares the common structure defined by the class…• …but has it's own copy of the attributes
• Sound familiar?– We've seen this with C structs– …struct's are a limited form of classes
• classes can do everything struct's can, but not vice-versa
Basic example// Basically a structclass Monster{public:
int hp;char name[16];
};
int main(){Monster m1, m2;
m1.hp = 100;m2.hp = 50;strcpy(m1.name, “Ogre“); // string.h includedstrcpy(m2.name, "Goblin“);cout << m1.name << " has " << m1.hp << "hp" << endl;
}
Basic Example…add methods
class Monster{public:
int hp;char name[16];void takeDamage(int amt) // an inline method{
hp = hp – amt < 0 ? 0 : hp – amt;cout << "Ouch!" << endl;
}void heal(); // method prototype
};
void Monster::heal() // non-inline method definition{
hp = 100;cout << "Ahhhh" << endl;
}
int main(){Monster m1, m2;
m1.hp = 100;m2.hp = 50;strcpy(m1.name, "Ogre“);strcpy(m2.name, "Goblin“);m1.takeDamage(5);cout << m1.name << " has " << m1.hp << "hp" << endl;m1.heal();
}
Basic Example…add methods
void Monster::heal() // non-inline method definition{
hp = 100;cout << "Ahhhh" << endl;
}
• All instances have their own copy of attributes (see the first version of main)
• All instances share the same object code for methods.
• So…on the line "hp = 100;", whose hp is changing?– The answer involves the keyword this.
this
• Any time a method of an object is called:– The normal registers, parameters, etc. are created on the
stack.– In addition, a pointer to the calling object is put on the
stack as well (this). • These 3 lines are all equivalent
hp = 100; // as it is on prev. slide(*this).hp = 100;// de-reference thisthis->hp = 100; // shorthand for above
• [Show the stack on prev. example]
Part II: Constructors / Destructors
• [Motivation]• Called automatically when:
– constructor: a new instance is made– destructor: an instance is destroyed
• When stack-based variables go out of scope• When heap-based data is deallocated
• Uses of constructor– Guarantee that all data has been initialized– Run any "startup" code
• Uses of destructor– Run an cleanup code– Often: de-allocate memory
Constructors / Destructors, cont.
• Both the constructor and destructor look like functions– No return values, though.– Name must be exactly the same as the class– Destructor has a tilde (~) before it.
• In the constructor, you can [slightly quicker] initialize your attributes using the colon operator
• You can overload the constructor (have multiple versions)
Constructor / Destructor exampleclass Sprite{public:
Sprite(); // "Default" constructorSprite(char * fname); // "Loader" constructor~Sprite(); // Destructorint load(char * fname);
protected:SDL_Surface * mSurf;int mWidth, int mHeight;
};
Sprite::Sprite() : mSurf(NULL), mWidth(-1), mHeight(-1){}
Sprite::Sprite(char * fname) {
mSurf = NULL; // Possibly a bit slower than using colon op.mWidth = -1;mHeight = -1;load(fname);
}
Constructor / Destructor exampleSprite::~Sprite(){
if (mSurf)SDL_FreeSurface(mSurf);
}
int Sprite::load(char * fname){
mSurf = SDL_LoadBMP(fname);if (mSurf){
mWidth = mSurf->w;mHeight = mSurf->h;return 1;
}return 0;
}
III. Miscellaney
• Class (static) attributes and methods– "Normal" attributes are instance attributes
• Each instance has its own copy
– "Normal" methods are shared by all instances, but this is passed so we can access instance attributes
– Static attributes are shared by all instances (only one copy per class)• We can have a static attribute without any instances!
– Static methods are also shared, but don't have a this parameter• We don't have access to normal attributes
Static's example//---------------- Monster.h#ifndef _MONSTER_H_#define _MONSTER_H_#include <iostream>using namespace std;
class Monster{protected: int mScariness; // A normal (instance) attribute static int msNumInstances; // A static (class) attributepublic: Monster(int slvl); // A normal (instance) method ~Monster(); // A normal (instance) method void roar(); // A normal (instance) method static int getNumInstances(); // A static (class) method};
#endif
Static's example, cont.//---------------- Monster.cpp#include "Monster.h"
int Monster::msNumInstances = 0; // Note the static variables initialization
Monster::Monster(int slvl) : mScariness(slvl){ msNumInstances++; // Note: We can access static attributes in // a normal method}
Monster::~Monster(){ msNumInstances--;}
void Monster::roar(){ cout << "ROAR"; for (int i = 0; i < mScariness; i++) cout << "!"; cout << endl;}
int Monster::getNumInstances()// Note: don't put static keyword in the .cpp file{ // cout << mScariness << endl; // Error. Can’t access non-static’s return msNumInstances;}
Static's example, cont.//---------------- main.cpp#include "Monster.h"int main(){
cout << "#Monsters = " << Monster::getNumInstances() << endl; // cout << Monster::msNumInstances << endl; // Not allowed b/c // msNumInstances is protected Monster m1(5); Monster m2(7); Monster * mp; m1.roar(); m2.roar(); mp = new Monster(10); cout << "#Monsters = " << Monster::getNumInstances() << endl; mp->roar(); delete mp; cout << "#Monsters = " << Monster::getNumInstances() << endl;}
enum
• [Nothing to do with classes]• An integer, basically.• When defining the enum type, you can specify
the values which can be assigned– a word (more descriptive than a number)
enum example// Somewhere else (maybe in a .h file)enum Day {monday, tuesday, wednesday, thursday, friday, saturday, sunday};
int main(){Day d; d = wednesday; cout << d << endl;// 2 //d = funday;// Error //d = 18;// Error //d++;// Error d = (Day)((int)d + 1); cout << d << endl;// 3 d = (Day)55;// Allowed in VC2012, but a bad idea... cout << d << endl;}
IV. STL Intro• Standard Template Library• Uses templates (we'll touch on these later)
– I'll treat this part as "magic" for now…• A relatively new addition to C++• Automates a lot of tedious tasks that we do a lot.• Makes it more "Python"-ish.• Internally, though, it uses tools we've seen already• We'll look at vectors for now. Others include:
– [linked] lists– maps (similar to python dictionaries)– sets– …
Vectors
• A "dynamic" array• Behind the scenes, just an array
– With the current max and used size.• Can add and remove
– Adds at the end are OK – in the middle they're very slow.– Similar for removes
• Includes code to grow the array if we add more than max– Really, re-allocates it on the heap (larger), copies existing
data (SLOW!)• Supports array-indexing (through operator overloading)
Vector example#include <vector>#include <iostream>#include <string>using namespace std;
int main() {vector<int> vint;vector<string> vstr;unsigned int i;
vint.push_back(5); vint.push_back(7); vint.push_back(13); cout << "Vint contents" << endl << "=============" << endl; for (i=0; i<vint.size(); i++) cout << i << "\t" << vint[i] << endl; vint.pop_back(); vint.insert(vint.begin() + 1, 99); // Inserts at pos#1, moves everything 'down' cout << "Vint contents" << endl << "=============" << endl; for (i=0; i<vint.size(); i++) cout << i << "\t" << vint[i] << endl;
Vector example, cont.
vint.resize(7); cout << "Vint contents" << endl << "=============" << endl; for (i=0; i<vint.size(); i++) cout << i << "\t" << vint[i] << endl; cout << "Current max: " << vint.max_size() << endl; vint.clear(); cout << "Vint size: " << vint.size() << endl; // All the same operations are proved for strings (or any type) vstr.push_back("ABC"); vstr.push_back("XYZ"); //vstr.push_back(9);// ERROR!
}