C++におけるAbstract classの使用

9456 ワード

Abstract classes act as expressions of general concepts from which more specific classes can be derived. You cannot create an object of an abstract class type; however, you can use pointers and references to abstract class types.
A class that contains at least one pure virtual function is considered an abstract class. Classes derived from the abstract class must implement the pure virtual function or they, too, are abstract classes.
A pure Abstract class has only abstract member functions and no data or concrete member functions. In general, a pure abstract class is used to define an interface and is intended to be inherited by concrete classes. It's a way of forcing a contract between the class designer and the users of that class. The users of this class must declare a matching member function for the class to compile.
The purpose of an abstract class (often referred to as an ABC) is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface. Attempting to instantiate an object of an abstract class causes a compilation error.
Restrictions on abstract classes:
(1)、Abstract classes cannot be used for: Variables or member data; Argument types; Function return types; Types of explicit conversions.
(2)、if the constructor for an abstract class calls a pure virtual function, either directly or indirectly, the result is undefined. However, constructors and destructors for abstract classes can call other member functions.
(3)、not to declare an object of an abstract class. It can be used to declare pointers and references to an abstract class.
(4)、Abstract class cannot be instantiated, but pointers and references of Abstract class type can be created.
(5)、Abstract class can have normal functions and variables along with a pure virtual function.
(6)、Abstract classes are mainly used for Upcasting, so that its derived classes can use its interface.
(7)、Classes inheriting an Abstract Class must implement all pure virtual functions, or else they will become Abstract too.
An interface class is a class that has no members variables, and where all of the functions are pure virtual! In other words, the class is purely a definition, and has no actual implementation. Interfaces are useful when you want to define the functionality that derived classes must implement, but leave the details of how the derived class implements that functionality entirely up to the derived class.
C++では、継承されたオブジェクトのみで直接作成できないクラスを抽象クラス(Abstract Class)に設定できます.
純虚関数は、ベースクラスで宣言された虚関数です.ベースクラスでは定義されていませんが、派生クラスには独自の実装方法を定義する必要があります.基底クラスで純虚関数を実現する方法は,関数プロトタイプに「=0」を付ける.
多くの場合、ベースクラス自体がオブジェクトを生成するのは無理です.この問題を解決するために,純粋虚関数の概念を導入し,関数を純粋虚関数として定義すると,コンパイラは派生クラスで多態性を実現するために書き換えなければならないことを要求する.純粋な仮想関数を同時に含むクラスを抽象クラスと呼びます.抽象クラスには定義されていない純粋な虚関数が含まれているため、オブジェクトを生成できません.
純粋な虚関数は特殊な虚関数であり、宣言のみであり、具体的な定義はありません.抽象クラスには少なくとも1つの純虚関数が存在する.純粋な虚関数が存在するクラスは抽象クラスに違いない.
インタフェースは、クラスの特定の実装を完了する必要がなく、クラスの動作と機能を記述する.C++インタフェースは抽象クラスを用いて実現される.
抽象クラスから派生した新しいクラスでベースクラスのすべての純虚関数を定義すると,これらの関数には機能が与えられ,呼び出される.この派生クラスは抽象クラスではなく、オブジェクトの特定のクラスを定義するために使用できます.派生クラスですべての純虚関数が定義されていない場合、この派生クラスは抽象クラスであり、オブジェクトを定義するために使用できません.
次は、他の記事のcopyのテストコードです.詳細は、対応するreferenceを参照してください.
#include "abstract_class.hpp"
#include 

///////////////////////////////////////////////////
// reference: https://msdn.microsoft.com/zh-cn/library/c8whxhf1.aspx
// Declare an abstract base class with a pure virtual destructor.
class base {
public:
	base() {}
	virtual ~base() = 0;
};

// Provide a definition for destructor.
base::~base() { fprintf(stderr, " base destructor "); }

class derived :public base {
public:
	derived() {}
	~derived(){ fprintf(stderr, " derived destructor "); }
};

int test_abstract_class1()
{
	derived *pDerived = new derived;
	// When the object pointed to by pDerived is deleted,
	// the destructor for class derived is called and then the destructor for class base is called.
	delete pDerived; // derived destructor base destructor

	return 0;
}

//////////////////////////////////////////////
// reference: http://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm
// Base class
class Shape_
{
public:
	// pure virtual function providing interface framework.
	virtual int getArea() = 0;
	void setWidth(int w)
	{
		width = w;
	}
	void setHeight(int h)
	{
		height = h;
	}
protected:
	int width;
	int height;
};

// Derived classes
class Rectangle : public Shape_
{
public:
	int getArea()
	{
		return (width * height);
	}
};
class Triangle : public Shape_
{
public:
	int getArea()
	{
		return (width * height) / 2;
	}
};

int test_abstract_class2()
{
	Rectangle Rect;
	Triangle  Tri;

	Rect.setWidth(5);
	Rect.setHeight(7);
	// Print the area of the object.
	std::cout << "Total Rectangle area: " << Rect.getArea() << std::endl;

	Tri.setWidth(5);
	Tri.setHeight(7);
	// Print the area of the object.
	std::cout << "Total Triangle area: " << Tri.getArea() << std::endl;

	return 0;
}

//////////////////////////////////////////////////
// reference: https://www.codingunit.com/cplusplus-tutorial-polymorphism-and-abstract-base-class
class CPolygon
{
protected:
	int width, height;
public:
	void setup(int first, int second)
	{
		width = first;
		height = second;
	}
	virtual int area() = 0;
};

class CRectangle : public CPolygon
{
public:
	int area(void)
	{
		return (width * height);
	}
};

class CTriangle : public CPolygon
{
public:
	int area(void)
	{
		return (width * height / 2);
	}
};

int test_abstract_class3()
{
	CRectangle rectangle;
	CTriangle triangle;

	CPolygon * ptr_polygon1 = &rectangle;
	CPolygon * ptr_polygon2 = ▵

	ptr_polygon1->setup(2, 2);
	ptr_polygon2->setup(2, 2);

	std::cout << ptr_polygon1->area() << std::endl;
	std::cout << ptr_polygon2->area() << std::endl;

	return 0;
}

//////////////////////////////////////////////////
// reference: https://www.codingunit.com/cplusplus-tutorial-polymorphism-and-abstract-base-class
class CPolygon_4
{
protected:
	int width, height;
public:
	void setup(int first, int second)
	{
		width = first;
		height = second;
	}
	virtual int area(void) = 0;
	void onscreen(void)
	{
		std::cout << this->area() << std::endl;
	}
};

class CRectangle_4 : public CPolygon_4
{
public:
	int area(void)
	{
		return (width * height);
	}
};

class CTriangle_4 : public CPolygon_4
{
public:
	int area(void)
	{
		return (width * height / 2);
	}
};

int test_abstract_class4()
{
	{
		CRectangle_4 rectangle;
		CTriangle_4 triangle;

		CPolygon_4 * ptr_polygon1 = &rectangle;
		CPolygon_4 * ptr_polygon2 = ▵

		ptr_polygon1->setup(2, 2);
		ptr_polygon2->setup(2, 2);

		ptr_polygon1->onscreen();
		ptr_polygon2->onscreen();
	}

	{
		CPolygon_4 * ptr_polygon1 = new CRectangle_4;
		CPolygon_4 * ptr_polygon2 = new CTriangle_4;

		ptr_polygon1->setup(2, 2);
		ptr_polygon2->setup(2, 2);

		ptr_polygon1->onscreen();
		ptr_polygon2->onscreen();

		delete ptr_polygon1;
		delete ptr_polygon2;
	}

	return 0;
}

////////////////////////////////////
// reference: http://www.thegeekstuff.com/2014/07/cpp-inheritance-abstract-class/
class CFigure
{
protected:
	double dSide;
public:
	CFigure(double a){ dSide = a; };
	virtual       ~CFigure(){};
	virtual double Surface(void)const = 0;
	virtual double Circumference(void)const = 0;
	virtual double Side(void)const = 0;
};

class CSquare : public CFigure
{
public:
	CSquare(double a) :CFigure(a){};
	~CSquare(){};
	double Surface(void)const{ return dSide*dSide; }
	double Circumference(void)const{ return 4.0*dSide; }
	double Side(void)const{ return dSide; }
};

int test_abstract_class5()
{
	CSquare Square_1(1);

	std::cout << "Surface="
		<< Square_1.Surface() << std::endl
		<< "Circumference="
		<< Square_1.Circumference() << std::endl;

	CFigure* ptrFigure = new CSquare(2);
	std::cout << "Surface="
		<< ptrFigure->Surface() << std::endl
		<< "Circumference="
		<< ptrFigure->Circumference() << std::endl;

	delete ptrFigure;

	return 0;
}

///////////////////////////////////////////
// reference: https://www.eduonix.com/blog/system-programming/learn-abstract-classes-virtual-functions-c/
class point
{
protected:
	float x, y;
public:
	point(float px, float py)
	{
		x = px; y = py;
	}
};

class shape				// Abstract Class
{
public:
	virtual float perimeter() = 0;	//pure virtual function
	virtual float area() = 0;	//another pure virtual function
};

/* The circle class will inherit from both point and shape */
class circle : public point, public shape
{
	float radius;
public:
	circle(float x, float y, float rad) : point(x, y)
	{
		radius = rad;
	}
	float getRadius()
	{
		return radius;
	}
	float perimeter()
	{
		return 2 * 3.14 * radius;
	}
	float area()
	{
		return 3.14 * radius * radius;
	}
};

int test_abstract_class6()
{
	circle c(5, -1, 4);
	std::cout << "
For a circle with radius = " << c.getRadius(); std::cout << "
Perimeter: " << c.perimeter(); std::cout << "
Area: " << c.area() << std::endl; return 0; }

GitHub: https://github.com/fengbingchun/Messy_Test