C++ interface (abstract class) && processor

Name: Ah Yue's Little Dongdong

Learning: Python, C/C++

Home page link: A Yue's Xiaodongdong's blog_CSDN blog-python&&c++ advanced knowledge, essential for Chinese New Year, blogger in the field of C/C++ knowledge explanation

Table of contents

C++ interface

instance of an abstract class

example

Design Strategy

preprocessor

#define preprocessing

parameter macro

conditional compilation

example

# and ## operators

example


 

C++ interface

An interface describes the behavior and functionality of a class without requiring a specific implementation of the class to be done.

C++ interfaces are implemented using abstract classes . Abstract classes are not to be confused with data abstraction. Data abstraction is a concept that separates implementation details from related data.

A class is an abstract class if at least one function in the class is declared as a pure virtual function. Pure virtual functions are specified by using "= 0" in the declaration, as follows:

class Box
{
   public:
      // 纯虚函数
      virtual double getVolume() = 0;
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};

The purpose of designing abstract classes (commonly called ABCs) is to provide other classes with an appropriate base class from which to inherit. An abstract class cannot be used to instantiate objects, it can only be used as an interface . Attempting to instantiate an object of an abstract class will result in a compilation error.

Therefore, if a subclass of ABC needs to be instantiated, each pure virtual function must be implemented, which also means that C++ supports the use of ABC to declare interfaces. If the pure virtual function is not overridden in the derived class, trying to instantiate an object of this class will cause a compilation error.

A class that can be used to instantiate an object is called a concrete class .

instance of an abstract class

Please see the following example, the base class Shape provides an interface  getArea() , and getArea() is implemented in the two derived classes Rectangle and Triangle respectively  :

example

#include <iostream>
 
using namespace std;
 
// 基类
class Shape 
{
public:
   // 提供接口框架的纯虚函数
   virtual int getArea() = 0;
   void setWidth(int w)
   {
      width = w;
   }
   void setHeight(int h)
   {
      height = h;
   }
protected:
   int width;
   int height;
};
 
// 派生类
class Rectangle: public Shape
{
public:
   int getArea()
   { 
      return (width * height); 
   }
};
class Triangle: public Shape
{
public:
   int getArea()
   { 
      return (width * height)/2; 
   }
};
 
int main(void)
{
   Rectangle Rect;
   Triangle  Tri;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
   // 输出对象的面积
   cout << "Total Rectangle area: " << Rect.getArea() << endl;
 
   Tri.setWidth(5);
   Tri.setHeight(7);
   // 输出对象的面积
   cout << "Total Triangle area: " << Tri.getArea() << endl; 
 
   return 0;
}

When the above code is compiled and executed, it produces the following result:

Total Rectangle area: 35
Total Triangle area: 17

From the above example, we can see how an abstract class defines an interface getArea(), and how two derived classes implement the same function through different algorithms for calculating the area.

Design Strategy

An object-oriented system might use an abstract base class to provide an appropriate, common, standardized interface to all external applications. Then, the derived class inherits all similar operations by inheriting the abstract base class.

Functions provided by external applications (that is, public functions) exist as pure virtual functions in the abstract base class. These pure virtual functions are implemented in the corresponding derived classes.

This architecture also enables new applications to be easily added to the system, even after the system has been defined

preprocessor

Processors are instructions that tell the compiler what preprocessing to do before actual compilation.

All preprocessor directives begin with a pound sign (#), and only space characters can appear before a preprocessor directive. Preprocessing directives are not C++ statements, so they do not end with a semicolon (;).

We have seen that there are #include  directives in all the previous examples  . This macro is used to include header files into source files.

C++ also supports many preprocessing directives, such as #include, #define, #if, #else, #line, etc. Let us take a look at these important directives.

#define preprocessing

The #define preprocessing directive is used to create symbolic constants. This symbolic constant is usually called a macro , and the general form of the instruction is:

#define macro-name replacement-text 

When this line of code appears in a file, all subsequent occurrences of macros in that file will be replaced with replacement-text before the program is compiled. For example:

#include <iostream>
using namespace std;
 
#define PI 3.14159
 
int main ()
{
 
    cout << "Value of PI :" << PI << endl; 
 
    return 0;
}

Now, let's test this code and see the result of preprocessing. Assuming that the source code file already exists, then use the -E option to compile and redirect the result to test.p. Now, if you look at the test.p file, you'll see that it already contains a lot of information, and that the values ​​at the bottom of the file have been changed to the following:

$ gcc -E test.cpp > test.p

...
int main ()
{
 
    cout << "Value of PI :" << 3.14159 << endl; 

    return 0;
}

parameter macro

You can use #define to define a macro with parameters like this:

#include <iostream>
using namespace std;
 
#define MIN(a,b) (a<b ? a : b)
 
int main ()
{
   int i, j;
   i = 100;
   j = 30;
   cout <<"较小的值为:" << MIN(i, j) << endl;
 
    return 0;
}

When the above code is compiled and executed, it produces the following result:

Smaller value: 30

conditional compilation

There are several directives that can be used to selectively compile portions of program source code. This process is called conditional compilation.

The structure of the conditional preprocessor is very similar to the if selection structure. Consider the following preprocessor code:

#ifdef NULL
   #define NULL 0
#endif

You can compile only when debugging, the debug switch can be implemented with a macro like this:

#ifdef DEBUG
   cerr <<"Variable x = " << x << endl;
#endif

If the symbolic constant DEBUG has been defined before the directive #ifdef DEBUG, the cerr statement in the program will   be compiled. You can comment out part of a program with a #if 0 statement, like so:

#if 0 
   code that does not compile 
#endif

Let's try the following example:

example

#include <iostream>
using namespace std;
#define DEBUG
 
#define MIN(a,b) (((a)<(b)) ? a : b)
 
int main ()
{
   int i, j;
   i = 100;
   j = 30;
#ifdef DEBUG
   cerr <<"Trace: Inside main function" << endl;
#endif
 
#if 0
   /* 这是注释部分 */
   cout << MKSTR(HELLO C++) << endl;
#endif
 
   cout <<"The minimum is " << MIN(i, j) << endl;
 
#ifdef DEBUG
   cerr <<"Trace: Coming out of main function" << endl;
#endif
    return 0;
}

When the above code is compiled and executed, it produces the following result:

Trace: Inside main function
The minimum is 30
Trace: Coming out of main function

# and ## operators

The # and ## preprocessing operators are available in both C++ and ANSI/ISO C. The # operator converts the replacement-text token into a quoted string.

Please see the following macro definition:

#include <iostream>
using namespace std;
 
#define MKSTR( x ) #x
 
int main ()
{
    cout << MKSTR(HELLO C++) << endl;
 
    return 0;
}

When the above code is compiled and executed, it produces the following result:

HELLO C++

Let's see how it works. Not surprisingly, the C++ preprocessor puts the following line:

cout << MKSTR(HELLO C++) << endl;

converted to:

cout << "HELLO C++" << endl;

The ## operator is used to concatenate two tokens. Here is an example:

#define CONCAT( x, y )  x ## y

When CONCAT appears in a program, its arguments are concatenated and used instead of the macro. For example, CONCAT(HELLO, C++) in the program will be replaced with "HELLO C++", as shown in the example below.

example

#include <iostream>
using namespace std;
 
#define concat(a, b) a ## b
int main()
{
   int xy = 100;
   
   cout << concat(x, y);
   return 0;
}

When the above code is compiled and executed, it produces the following result:

100

Let's see how it works. Not surprisingly, the C++ preprocessor puts the following line:

cout << concat(x, y);

converted to:

cout << xy;

Guess you like

Origin blog.csdn.net/m0_64122244/article/details/132278198