繁体   English   中英

C ++中纯虚函数的用途是什么?

[英]What are the uses of pure virtual functions in C++?

我现在正在课堂上学习C ++,但我不太了解纯虚函数。 我知道它们稍后会在派生类中概述,但是如果您只想在派生类中对其进行定义,为什么还要将其声明为等于0?

简要地说,是使类抽象化,使其无法实例化,但是子类可以覆盖纯虚方法以形成具体的类。 这是在C ++中定义接口的好方法。

这将强制派生类定义函数。

包含纯虚方法的任何类都是抽象的,即无法实例化。 抽象类对于定义子类应该共享的某些核心行为很有用,但允许(实际上是要求)子类分别实现抽象。

一个抽象类的例子:

class Foo {

    // pure virtual, must be implemented by subclasses
    virtual public void myMethod() = 0;

    // normal method, will be available to all subclasses,
    // but *can* be overridden
    virtual public void myOtherMethod();
};

每个方法都是抽象的类可以用作接口,要求所有子类通过实现接口中包含的所有方法来符合该接口。

接口示例:

class Bar {

    // all method are pure virtual; subclasses must implement
    // all of them
    virtual public void myMethod() = 0;

    virtual public void myOtherMethod() = 0;
};

C ++中的纯虚拟方法基本上是一种定义接口而不需要实现它们的方法。

要添加到史蒂文·苏迪特的答案中:

“简而言之,是使类抽象化,使其无法实例化,但是子类可以覆盖纯虚方法以形成具体的类。这是在C ++中定义接口的好方法。”

例如,如果您有一个基类(也许是Shape),用于定义其派生类可以使用的许多成员函数,但又希望防止声明Shape的实例并强制用户仅使用Shape的实例。派生类(可能是Rectangle,Triangle,Pentagon等)

RE:Jeff以上的答案

非抽象类可以包含虚拟成员函数并被实例化。 实际上,对于重载成员函数而言,这是必需的,因为默认情况下C ++不会确定变量的运行时类型,但是使用virtual关键字定义时,它将确定。

考虑以下代码(为清楚起见,不包括访问器,修改器,构造函数等):

class Person{
  int age;

  public:
    virtual void print(){
      cout << age <<endl;
    }
}

class Student: public Person{
  int studentID

  public:
    void print(){
      cout << age << studentID <<endl;
    }
}

现在,当运行此代码时:

 Person p = new Student();
 p.print();

如果没有虚拟关键字,则只显示年龄,而不显示学生班级应该出现的年龄和学生ID

(此示例基于c ++中与Java程序员非常相似的http://www.amazon.com/Java-Programmers-Mark-Allen-Weiss/dp/013919424X

@Steven Sudit:你是完全正确的,我忽略了包括实际的继承,哦! 为了使内容更清晰,不包含访问器等,现在我已经使它变得更加明显。 3-7-09:全部固定

想象一下,我想对几种形状进行建模,并且所有形状都有明确定义的区域。 我决定每一个形状必须继承IShape (“我”的接口)和IShape将包括GetArea()方法:

class IShape {
    virtual int GetArea();
};

现在的问题是:如果该形状没有覆盖GetArea() ,该如何计算该形状的面积? 也就是说,最佳的默认实现是什么? 圆形使用pi * radius ^ 2,正方形使用length ^ 2,平行四边形和矩形使用base * height,三角形使用1/2 base * height,菱形,五边形,八边形等使用其他公式。

所以我说“通过定义纯虚拟方法,“如果您是形状,则必须定义一种计算面积的方法,但是如果我不知道这是什么,那就该死”。

class IShape {
    virtual int GetArea() = 0;
};

本质上,纯虚拟机用于创建接口(类似于java)。 这可以用作两个模块(或类,或其他)之间关于期望的功能类型的协议,而不必了解其他模块的实现。 这使您可以使用相同的接口轻松地即插即用,而无需更改正在使用该接口的其他模块中的任何内容。

例如:

class IStudent
{
    public:
    virtual ~IStudent(){};
    virtual std::string getName() = 0;
};


class Student : public IStudent
{
    public:
    std::string name;
    std::string getName() { return name; };
    void setName(std::string in) { name = in; };
};

class School
{
    public:
    void sendStudentToDetention(IStudent *in) {
        cout << "The student sent to detention is: ";
        cout << in->getName() << endl;
    };
};

int main()
{
    Student student;
    student.setName("Dave");

    School school;
    school.sendStudentToDetention(&student);
return 0;
}

学校不需要知道如何设置学生的名字,只需要知道如何获得学生的名字即可。 通过为学生提供实施和学校使用的界面,这两个部分之间就学校完成其工作所需的功能达成了协议。 现在,我们可以在不影响学校的情况下,切入和切出我们所需的Student类的不同实现(只要我们每次都实现相同的接口)。

抽象类的想法是,您仍然可以使用该类型声明一个变量(即,它是静态类型),但是该变量实际上引用或指向实际的具体类型(动态类型)。

在C ++中调用方法时,编译器需要确保该对象将支持该方法。

通过声明纯虚函数,您将放置一个“占位符”,编译器可使用该“占位符”来表示“哦……我知道该变量最终引用的内容都将接受该调用”,因为实际的具体类型将实现它。 但是,您不必提供抽象类型的实现。

如果您未声明任何内容,那么编译器将没有有效的方法来保证所有子类型都将实现它。

当然,如果您要问为什么要抽象一个类,那么有很多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM