📜  C++中的纯虚函数和抽象类

📅  最后修改于: 2021-05-30 15:30:00             🧑  作者: Mango

有时无法在基类中提供所有函数的实现,因为我们不知道实现。这样的类称为抽象类。例如,让Shape为基类。我们无法在Shape中提供函数draw()的实现,但是我们知道每个派生类都必须具有draw()的实现。类似地,Animal类也没有move()的实现(假设所有动物都移动了),但是所有动物都必须知道如何移动。我们不能创建抽象类的对象。
C++中的纯虚函数(或抽象函数)是我们可以为其实现的虚函数,但是我们必须在派生类中重写该函数,否则派生类也将成为抽象类(有关在何处提供的更多信息有关此类功能的实现,请参阅此https://stackoverflow.com/questions/2089083/pure-virtual-function-with-implementation)。通过在声明中分配0来声明纯虚函数。请参见以下示例。

CPP
// An abstract class
class Test
{  
    // Data members of class
public:
    // Pure Virtual Function
    virtual void show() = 0;
   
   /* Other members */
};


CPP
#include
using namespace std;
 
class Base
{
   int x;
public:
    virtual void fun() = 0;
    int getX() { return x; }
};
 
// This class inherits from Base and implements fun()
class Derived: public Base
{
    int y;
public:
    void fun() { cout << "fun() called"; }
};
 
int main(void)
{
    Derived d;
    d.fun();
    return 0;
}


C
// pure virtual functions make a class abstract
#include
using namespace std;
 
class Test
{
   int x;
public:
    virtual void show() = 0;
    int getX() { return x; }
};
 
int main(void)
{
    Test t;
    return 0;
}


CPP
#include
using namespace std;
 
class Base
{
public:
    virtual void show() = 0;
};
 
class Derived: public Base
{
public:
    void show() { cout << "In Derived \n"; }
};
 
int main(void)
{
    Base *bp = new Derived();
    bp->show();
    return 0;
}


CPP
#include
using namespace std;
class Base
{
public:
    virtual void show() = 0;
};
 
class Derived : public Base { };
 
int main(void)
{
  Derived d;
  return 0;
}


CPP
#include
using namespace std;
 
// An abstract class with constructor
class Base
{
protected:
int x;
public:
virtual void fun() = 0;
Base(int i) {
              x = i;
            cout<<"Constructor of base called\n";
            }
};
 
class Derived: public Base
{
    int y;
public:
    Derived(int i, int j):Base(i) { y = j; }
    void fun() { cout << "x = " << x << ", y = " << y<<'\n'; }
};
 
int main(void)
{
    Derived d(4, 5);
    d.fun();
   
  //object creation using pointer of base class
    Base *ptr=new Derived(6,7);
      ptr->fun();
    return 0;
}


一个完整的例子:
纯粹的虚函数由从Abstract类派生的类实现。以下是一个简单的示例来演示相同的内容。

CPP

#include
using namespace std;
 
class Base
{
   int x;
public:
    virtual void fun() = 0;
    int getX() { return x; }
};
 
// This class inherits from Base and implements fun()
class Derived: public Base
{
    int y;
public:
    void fun() { cout << "fun() called"; }
};
 
int main(void)
{
    Derived d;
    d.fun();
    return 0;
}

输出:

fun() called

一些有趣的事实:
1)如果一个类至少具有一个纯虚函数,则它是抽象的。
在下面的示例中,Test是一个抽象类,因为它具有纯虚函数show()。

C

// pure virtual functions make a class abstract
#include
using namespace std;
 
class Test
{
   int x;
public:
    virtual void show() = 0;
    int getX() { return x; }
};
 
int main(void)
{
    Test t;
    return 0;
}

输出:

Compiler Error: cannot declare variable 't' to be of abstract
 type 'Test' because the following virtual functions are pure 
within 'Test': note:     virtual void Test::show() 

2)我们可以有抽象类类型的指针和引用。
例如,以下程序可以正常运行。

CPP

#include
using namespace std;
 
class Base
{
public:
    virtual void show() = 0;
};
 
class Derived: public Base
{
public:
    void show() { cout << "In Derived \n"; }
};
 
int main(void)
{
    Base *bp = new Derived();
    bp->show();
    return 0;
}

输出:

In Derived 

3)如果我们不重写派生类中的纯虚函数,则派生类也将成为抽象类。
下面的示例演示了相同的内容。

CPP

#include
using namespace std;
class Base
{
public:
    virtual void show() = 0;
};
 
class Derived : public Base { };
 
int main(void)
{
  Derived d;
  return 0;
}
Compiler Error: cannot declare variable 'd' to be of abstract type 
'Derived'  because the following virtual functions are pure within
'Derived': virtual void Base::show() 

4)抽象类可以具有构造函数。
例如,以下程序可以编译并正常运行。

CPP

#include
using namespace std;
 
// An abstract class with constructor
class Base
{
protected:
int x;
public:
virtual void fun() = 0;
Base(int i) {
              x = i;
            cout<<"Constructor of base called\n";
            }
};
 
class Derived: public Base
{
    int y;
public:
    Derived(int i, int j):Base(i) { y = j; }
    void fun() { cout << "x = " << x << ", y = " << y<<'\n'; }
};
 
int main(void)
{
    Derived d(4, 5);
    d.fun();
   
  //object creation using pointer of base class
    Base *ptr=new Derived(6,7);
      ptr->fun();
    return 0;
}

输出:

Constructor of base called
x = 4, y = 5
Constructor of base called
x = 6, y = 7

与Java的比较
在Java,可以使用abstract关键字将类抽象化。类似地,可以通过使用abstract关键字使函数成为纯虚函数或抽象函数。看
有关更多详细信息,请参见Java的抽象类。
接口与抽象类:
接口没有任何方法的实现,可以将其视为方法声明的集合。在C++中,可以通过将所有方法设为纯虚拟方法来模拟接口。在Java,接口有一个单独的关键字。

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”