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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1071092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:41:39  来源:igfitidea点击:

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

c++virtual-functionspure-virtual

提问by patricksweeney

I'm learning about C++ in a class right now and I don't quite grok pure virtual functions. I understand that they are later outlined in a derived class, but why would you want to declare it as equal to 0 if you are just going to define it in the derived class?

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

回答by Steven Sudit

Briefly, it's to make the class abstract, so that it can't be instantiated, but a child class can override the pure virtual methods to form a concrete class. This is a good way to define an interface in C++.

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

回答by Jim Buck

This forces a derived class to define the function.

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

回答by Jeff L

Any class containing a pure virtual method will be abstract, that is, it cannot be instantiated. Abstract classes are useful for defining some core behavior that subclasses should share, but allowing (in fact, requiring) subclasses to implement the abstract individually.

任何包含纯虚方法的类都是抽象的,也就是说,它不能被实例化。抽象类对于定义子类应该共享的一些核心行为很有用,但允许(实际上,需要)子类单独实现抽象。

An example of an abstract class:

抽象类的一个例子:

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();
};

A class in which every method is abstract can be used as an interface, requiring all subclasses to conform to the interface by implementing all methods contained in it.

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

An example of an interface:

接口示例:

class Bar {

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

    virtual public void myOtherMethod() = 0;
};

回答by none

Pure virtual methods in C++ are basically a way to define interfaceswithout requiring them to be implemented.

C++ 中的纯虚方法基本上是一种无需实现接口即可定义接口的方法。

回答by chrisbunney

To add to Steven Sudit's answer:

添加到 Steven Sudit 的回答中:

"Briefly, it's to make the class abstract, so that it can't be instantiated, but a child class can override the pure virtual methods to form a concrete class. This is a good way to define an interface in C++."

“简而言之,就是把类抽象化,这样就不能被实例化,但是子类可以覆盖纯虚方法,形成一个具体的类。这是在C++中定义接口的好方法。”

An example of this would be if you had a base class (perhaps Shape) that you use to define a number of member functions that its derived classes can use, but want to prevent an instance of Shape being declared and force users to use only the derived classes (which may be, Rectangle, Triangle, Pentagon, and so on)

这方面的一个例子是,如果您有一个基类(可能是 Shape),用于定义其派生类可以使用的许多成员函数,但想要防止声明 Shape 的实例并强制用户仅使用派生类(可能是 Rectangle、Triangle、Pentagon 等)

RE: Jeff's answer above

RE:上面杰夫的回答

Non-abstract classes can contain virtual member functions and be instantiated. In fact, for overloading member functions this is required as by default C++ doesn't determine the runtime type of a variable, but when defined using th virtual keyword, it will.

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

Consider this code (note, accessors, mutators, constructors, etc are not included for the sake of clarity):

考虑这段代码(注意,为了清楚起见,不包括访问器、修改器、构造器等):

class Person{
  int age;

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

class Student: public Person{
  int studentID

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

Now when running this code:

现在运行此代码时:

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

without the virtual keyword, only the age would be printed, not the age and studentID as is supposed to happen for the Student class

如果没有 virtual 关键字,则只会打印年龄,而不是像 Student 类应该发生的年龄和学生 ID

(this example is based on a very similar one from c++ for java programmers http://www.amazon.com/Java-Programmers-Mark-Allen-Weiss/dp/013919424X)

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

@Steven Sudit: you are completely correct, I neglected to include the actual inheritance, doh! The accessors etc aren't included to keep things clearer, and I've made that more obvious now. 3-7-09: all fixed

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

回答by Max Lybbert

Imagine I want to model several kinds of shapes, and all have a well-defined area. I decide that every shape must inherit IShape("I" for interface), and IShapewill include a GetArea()method:

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

class IShape {
    virtual int GetArea();
};

Now the problem: how should I calculate the area of a shape if that shape doesn't override GetArea()? That is, what is the best default implementation? Circles use pi*radius^2, squares use length^2, parallelograms and rectangles use base*height, triangles use 1/2 base*height, rhombuses, pentagons, octagons, etc. use other formulas.

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

So I say "if you're a shape you must define a way to calculate the area, but damned if I know what that will be" by defining the method pure virtual:

所以我说“如果你是一个形状,你必须定义一种计算面积的方法,但如果我知道那会是什么,那该死的”通过定义纯虚拟方法:

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

回答by davidivins

Essentially, pure virtuals are used to create an interface (similar to java). This can be used as an agreement between two modules (or classes, or whatever) as to what kind of functionality to expect, without having to know anything about the implementation of the other piece. This allows you to easily plug and play pieces using the same interface without having to change anything in the other module which is using your interface.

本质上,纯虚拟用于创建接口(类似于 java)。这可以用作两个模块(或类,或其他)之间关于预期什么样的功能的协议,而无需了解其他部分的实现。这使您可以使用相同的界面轻松地即插即用,而无需更改使用您的界面的其他模块中的任何内容。

For example:

例如:

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;
}

The school doesn't need to know how to set a student's name, all it needs to know is how to get the student's name. By providing an interface for Student to implement and the school to use, there's an agreement between the two pieces about what functionality is needed by school to perform its job. Now we can switch in and out different implementations of the Student class all we want without affecting the school (as long as we implement the same interface each time).

学校不需要知道如何设置学生的名字,它只需要知道如何获取学生的名字。通过提供一个接口供学生实现和学校使用,这两个部分就学校需要什么功能来执行其工作达成了一致。现在我们可以在不影响学校的情况下随意切换 Student 类的不同实现(只要我们每次实现相同的接口)。

回答by Uri

The idea with abstract classes is that you can still have a variable declared with that type (i.e., it is the static type), but the variable actually refers or points to an actual concrete type (the dynamic type).

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

When you invoke a method in C++, the compiler needs to make sure that the method would be supported on that object.

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

By declaring the pure virtual function, you are putting a "placeholder" that the compiler can use to say "oh... I know that whatever ends up being referred to by this variable will accept that call" because the actual concrete types will implement it. However, you don't have to provide an implementation in the abstract type.

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

If you didn't declare anything, then the compiler would have no effective way of guaranteeing that it would be implemented by all subtypes.

如果你没有声明任何东西,那么编译器就没有有效的方法来保证它会被所有的子类型实现。

Of course, if you're asking why you would want to make a class abstract, there's a lot of info around on that.

当然,如果你问为什么要抽象类,有很多关于这方面的信息。