// Tip #1: Avoid one-off errors.
void MyFunction()
{
int MyArray[10];
int i;
// Accessing a non-existent member of the array
for(i=0; i<=10; i++)
MyArray[i]=i;
// Accessing a only the members of the array
for(i=0; i<10; i++)
MyArray[i]=i;
};
// Tip #2: Use structures to make relationships between data clearer.
// A bad declaration:
int X;
int Y;
int W;
int H;
// A better declaration
struct SimpleRectangle
{
public:
int x; // Position on X axis
int y; // Position on Y axis
int w; // Width
int h; // Height
};
// Tip #4: Use structured data to make parameter
// passing
clearer, easier and simpler.
class BadRectangle // How not to do it!
{
public:
int rx; // Position on X axis
int ry; // Position on Y axis
int rw; // Width
int rh; // Height
BadRectangle(int x,int y,int w,int h);
void SetBounds(int x,int y,int w,int h);
void Display(int x,int y,int w,int h);
void Erase(int x,int y,int w,int h);
};
BadRectangle::BadRectangle(int x,int y,int w,int h)
{
SetBounds(x,y,w,h);
Display(x,y,w,h);
}
void BadRectangle::SetBounds(int x,int y,int w,int h)
{
// Tip #3: Use structured data to make
operations
// of blocks of
data simpler.
rx=x;
ry=y;
rw=w;
rh=h;
}
void BadRectangle::Display(int x,int y,int w,int h)
{
// Code to display the rectangle would go here
}
void BadRectangle::Erase(int x,int y,int w,int h)
{
// Code to erase the rectangle would go here
}
// Preferred declaration:
class BaseRectangle
{
public:
int x; // Position on X axis
int y; // Position on Y axis
int w; // Width
int h; // Height
BaseRectangle & operator = (const BaseRectangle& rect);
};
BaseRectangle & BaseRectangle::operator = (const BaseRectangle& rect)
{
if ((this->x == rect.x) &&
(this->y == rect.y) &&
(this->w == rect.w) &&
(this->h == rect.h))
return *this; // Check for
assignment to self
this->x = rect.x; // Copy the class elements - X-axis
position
this->y = rect.y; // Copy the class elements - Y-axis
position
this->w = rect.w; // Copy the class elements - Width
this->h = rect.h; // Copy the class elements - Height
return *(this); // Always return a pointer to
"this"!
}
class GoodRectangle // The preferred way to do it!
{
public:
BaseRectangle CurrentRectangle;
GoodRectangle(BaseRectangle rect);
void SetBounds(BaseRectangle rect);
void Display(BaseRectangle rect);
void Erase(BaseRectangle rect);
};
GoodRectangle::GoodRectangle(BaseRectangle rect)
{
SetBounds(rect); // Simpler parameters
Display(rect); // and easier block operations
}
void GoodRectangle::SetBounds(BaseRectangle rect)
{
// Tip #3: Use structured data to make operations
// of blocks of
data simpler.
CurrentRectangle = rect;
}
void GoodRectangle::Display(BaseRectangle rect)
{
// Code to display the rectangle would go here
}
void GoodRectangle::Erase(BaseRectangle rect)
{
// Code to erase the rectangle would go here
}
// Any time you work with an aggregate entity,
// you're working with an abstraction. Abstractions
// make things simpler and easier to understand.
void main()
{
BaseRectangle MyRectangle;
MyRectangle.x=1;
MyRectangle.y=2;
MyRectangle.w=10;
MyRectangle.h=15;
GoodRectangle MyGoodRectangle(MyRectangle);
BadRectangle MyBadRectangle(1,2,10,15);
MyFunction(); // This will crash due to the one-off error!
};