Those are all questions which can be found in any c++ book for sure.
the ... : when you don't know how many parameters you gonna have, printf is a nice example there.
virtual functions : when you have such a situation with the class theclass and theotherclass like above, and you have a virtual function in the base class, and you got a pointer like instance, you can call the function in the base class, and in case it is defined in the derived class, that one that was instantiated with your "new" statement, that function will be called, overriding the function from the base class.
such sort of behaviour is really useful when you just define an interface of a class and you have some derived classes. then you don't need to reimplement your algorithm for each data type, you can just implement it for this class and its interface. This principle is also the reason for making destructors virtual. when you delete an object where you are not sure of the type, and you delete some pointer to some base class, the topmost destructor will be called as well. without being virtual only the destructors of the class which are 'below' the type of which the pointer was are called.
I believe that this stuff isnt something you can really learn by reading, you have to have own projects where you need such mechanisms.
just an example from my bot's system to handle entities around it:
Code:
class CIEntity
{
public:
CIEntity();
CIEntity(const char *,bool);
virtual ~CIEntity();
bool compare(CEntity&);
void assign(CEntity&,CPerceipt *);
virtual bool isValid(CEntity&); // looks if this entity is valid - for weapons e.g. look if there's an owner ... if there is one, someone carries it, it's uninteresting
virtual Vector getWPOrigin(CEntity&); // get the location ... may not be pEdict->v.origin for some enteties
virtual const Vector &getOrigin(CEntity&); // get location - for distance and visibility checks
virtual long addWP(CEntity&); // add a waypoint at this entity
[....]
here I define the basic functionality. Now I can define some derived classes, put them all together ( some different classes, but they are based on the same base class ) into a list and then just loop thru them when percepting stuff.
Code:
m_LIEntities.push_back(pIEntity = new CInterestingWeapon("weaponbox",-1,false));
m_iIEntityIdWBox = pIEntity->m_iId;
m_LIEntities.push_back(pIEntity = new CIEntity("laser_spot",false));
m_LIEntities.push_back(pIEntity = new CIEntity("info_player_deathmatch",true));
m_LIEntities.push_back(pIEntity = new CInterestingLadder("func_ladder"));
at the perception stuff, I don't wanna care anymore if a weaponbox's origin is at entity->getOrigin, or at entity->getOwner()->GetOrigin(), here I just wanna have stuff as simple as possible.
Code:
while(Entity = UTIL_FindEntityInSphere(Entity,VOrigin,_ENT_PERC_RADIUS)){ // loop thru entities around here
iter_entities = begin_entities;
while(iter_entities != end_entities){
// check this entity
if( (*iter_entities)->compare(Entity) ){
if(m_pBot->views((*iter_entities)->getOrigin(Entity))){
pAllocPerc = new CPerceipt; // create a new perceipt
(*iter_entities)->assign(Entity,pAllocPerc);
pAllocPerc->m_fDistance = (VOrigin-pAllocPerc->m_VOrigin).length(); // todo : more elegant
m_LNewPerceptions.push_back(pAllocPerc);
break; // there arent double classname IEntities !? am I right ?
}
}
iter_entities ++;
}
}
Inheriting private classes : can't think of an example here, but you can e.g. inherit a stack data type instead of making it a member variable if that's "coherent with your philosophy", so if your data type _is_ basically a stack, but you just write another interface for it.