Home

Abstract Classes

 

Introduction

An abstract class is one whose role is only meant to lay a foundation for other classes that would need a common behavior or similar characteristics. Therefore, an abstract class is used only as a base class for inheritance. A class is made abstract by declaring its methods as "pure" virtual methods.

Only a virtual method can be made "pure". The syntax of declaring a pure virtual method is:

virtual ReturnType MethodName() = 0;

The virtual keyword is required to make sure that a (any) child of this class can implement this method as it judges it necessary. The ReturnType is the data type that the method will return. The MethodName is an appropriate name for the method. The = 0 expression is required to let the compiler know that this method is pure virtual.

When creating an abstract class, you can declare all of its methods as pure. Here is an example:

public ref class CQuadrilateral
{
public:
    virtual double Perimeter() = 0;
    virtual double Area() = 0;
};

To indicate that the class is abstract, type the abstract keyword after its name. Here is an example:

public ref class CQuadrilateral abstract
{
public:
    virtual double Perimeter() = 0;
    virtual double Area() = 0;
};

In C++/CLI, if you omit the abstract keyword, you would receive a warning.

Not all methods of an abstract class have to be pure virtual. This means that regular virtual methods can also be members of an abstract class. Here is an example:

public ref class CQuadrilateral abstract
{
public:
    virtual String ^ Description();
    virtual double Perimeter() = 0;
    virtual double Area() = 0;
    virtual void   Display() = 0;
};

A property can also be a member of an abstract class. If you declare a property in an abstract class, don't use the = 0 expression on the property. Here is an example:

public ref class CQuadrilateral abstract
{
public:
    virtual property double Base;

    virtual String ^ Description();
    virtual double Perimeter() = 0;
    virtual double Area() = 0;
    virtual void   Display() = 0;
};

You can also add regular member variables in an abstract class. You can even make some private, some public, and some protected. Here are examples:

public ref class CQuadrilateral abstract
{
private:
    double bs;

protected:
    String ^ Name;

public:
    virtual property double Base;

    virtual String ^ Description();
    virtual double Perimeter() = 0;
    virtual double Area() = 0;
    virtual void   Display() = 0;
};

An abstract class can also have one or more constructors:

public ref class CQuadrilateral abstract
{
private:
    double bs;

protected:
    String ^ Name;

public:
    virtual property double Base;

    virtual String ^ Description();
    virtual double Perimeter() = 0;
    virtual double Area() = 0;
    virtual void   Display() = 0;

    CQuadrilateral();
};

When a class is defined as abstract, you can implement any of its properties if you want. If a method is not made pure virtual, you can also define it. Here are examples:

public ref class CQuadrilateral abstract
{
private:
	double bs;

public:
	String ^ Name;
	virtual property double Base
	{
		double get() { return bs; }
		void set(double b)
		{
			if( b <= 0 )
				bs = 0.00;
			else
				bs = b;
		}
	}

	String ^ Description();

	virtual double Perimeter() = 0;
	virtual double Area() = 0;

	CQuadrilateral();

};

CQuadrilateral::CQuadrilateral()
{
	Name = L"Quadrilateral";
}

String ^ CQuadrilateral::Description()
{
	return L"A quadrilateral is a geometric figure with four sides";
}

After creating an abstract class, even if you implement (some of) its properties and methods, you cannot use the class. That is, you cannot declare a variable or handle of the class. This is because the class is not complete. Remember that it has at least one method that is not defined.

Deriving From an Abstract Class

Because an abstract class is not complete, you cannot (yet) use it. If you want to use it, you must derive a class from it. If you decide to derive a class from an abstract one, you must implement every one of its pure virtual methods in the new class. If you omit or forget defining a pure virtual method, you would receive an error.

When declaring the pure virtual methods in the new class, replace the = 0 expression with the override method. For the regular virtual properties or methods, you must flag them with either the override or the new keyword. Here is an example of a class that derives from an abstract class:

public ref class CSquare : public CQuadrilateral
{
public:
	CSquare();

	virtual String ^ Description() new;
	virtual double Perimeter() override;
	virtual double Area() override;
	virtual void   Display() override;
};

Based on this, in the new class, define the pure virtual method(s) as you want. After defining the new class, you can then instantiate it and use it as necessary. Here is an example:

using namespace System;

public ref class CQuadrilateral abstract
{
private:
	double bs;

protected:
	String ^ Name;

public:
	virtual property double Base
	{
		double get() { return bs; }
		void set(double b)
		{
			if( b <= 0 )
				bs = 0.00;
			else
				bs = b;
		}
	}

	virtual String ^ Description();

	virtual double Perimeter() = 0;
	virtual double Area() = 0;
	virtual void   Display() = 0;

	CQuadrilateral();

};

CQuadrilateral::CQuadrilateral()
{
	Name = L"Quadrilateral";
}

String ^ CQuadrilateral::Description()
{
	return L"A quadrilateral is a geometric figure with four sides";
}

public ref class CSquare : public CQuadrilateral
{
public:
	CSquare();

	virtual String ^ Description() new;
	virtual double Perimeter() override;
	virtual double Area() override;
	virtual void   Display() override;
};

CSquare::CSquare()
{
	Name = L"Square";
}

String ^ CSquare::Description()
{
	return L"A square is a quadrilateral with four equal sides";
}

double CSquare::Perimeter()
{
	return 4 * Base;
}

double CSquare::Area()
{
	return Base * Base;
}

void CSquare::Display()
{
	Console::WriteLine(L" === Shape Properties ===");
	Console::WriteLine(L"Name:        {0}", Name);
	Console::WriteLine(L"Description: {0}", CQuadrilateral::Description());
	Console::WriteLine(L"             {0}", Description());
	Console::WriteLine(L"Side:        {0}", Base);
	Console::WriteLine(L"Perimeter:   {0}", Perimeter());
	Console::WriteLine(L"Area:        {0}", Area());
}

int main()
{	
	CSquare ^ sqr = gcnew CSquare;

	sqr->Base = 22.46;
	sqr->Display();

	Console::WriteLine();
	return 0;
}

This would produce:

=== Shape Properties ===
Name:        Square
Description: A square is a quadrilateral with four equal sides
Side:        22.46
Perimeter:   89.84
Area:        504.4516

Press any key to continue . . .
 

Previous Copyright © 2006 FunctionX, Inc. Next