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"。
在很多情况下,基类本身生成对象是不合情理的。为了解决这个问题,引入了纯虚函数的概念,将函数定义为纯虚函数,则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,由于抽象类包含了没有定义的纯虚函数,它不能生成对象。
纯虚函数是一种特殊的虚函数,它只有声明,没有具体的定义。抽象类中至少存在一个纯虚函数;存在纯虚函数的类一定是抽象类。
接口描述了类的行为和功能,而不需要完成类的特定实现.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 << "\nFor a circle with radius = " << c.getRadius();
std::cout << "\nPerimeter: " << c.perimeter();
std::cout << "\nArea: " << c.area() << std::endl;
return 0;
}