Pregunta

Estoy aprendiendo sobre C ++ en una clase en este momento y no acabo de asimilar las funciones virtuales puras. Tengo entendido que se describen más adelante en una clase derivada, pero ¿para qué quieren declararlo como igual a 0 si sólo se va a definir en la clase derivada?

¿Fue útil?

Solución

En pocas palabras, es para hacer la clase abstracta, por lo que no se pueden crear instancias, pero una clase hija puede anular los métodos virtuales puros para formar una clase concreta. Esta es una buena manera de definir una interfaz en C ++.

Otros consejos

Esto obliga a una clase derivada para definir la función.

Cualquier clase que contiene un método virtual pura será abstracto, es decir, no se pueden crear instancias. Las clases abstractas son útiles para definir un comportamiento fundamental de que las subclases deben compartir, pero permitiendo (de hecho, lo que requiere) subclases para implementar el resumen individual.

Un ejemplo de una clase abstracta:

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

Una clase en la que cada método es abstracto se puede utilizar como una interfaz, requiriendo todas las subclases para ajustarse a la interfaz mediante la aplicación de todos los métodos contenidos en el mismo.

Un ejemplo de una interfaz:

class Bar {

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

    virtual public void myOtherMethod() = 0;
};

métodos virtuales puros en C ++ son básicamente una forma de definir las interfaces sin que tengan que ser implementadas.

Imaginemos que quiero para modelar varios tipos de formas, y todas tienen un área bien definida. Decido que cada forma debe heredar IShape ( "I" para la interfaz), y GetArea() incluirá un método <=>:

class IShape {
    virtual int GetArea();
};

Ahora el problema: ¿cómo debo calcular el área de una figura que se forma si no anula <=>? Es decir, ¿cuál es la mejor aplicación por defecto? Círculos utilizan pi * radio ^ 2, cuadrados utilizan longitud ^ 2, paralelogramos y rectángulos de uso base * altura, triángulos utilizan altura media de base *, rombos, pentágonos, octógonos, etc. utilizar otras fórmulas.

Por eso digo "si usted es una forma debe definir una forma de calcular el área, pero maldito si sé lo que habrá" definiendo el método virtual pura:

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

Para añadir a la respuesta de Steven Sudit:

"En pocas palabras, es para hacer la clase abstracta, por lo que no se pueden crear instancias, pero una clase hija puede anular los métodos virtuales puros para formar una clase concreta. Esta es una buena manera de definir una interfaz en C ++. "

Un ejemplo de esto sería si tuviera una clase base (tal vez de forma) que se utiliza para definir una serie de funciones miembro que sus clases derivadas pueden usar, pero desea evitar que una instancia de la forma de ser declarado y obligar a los usuarios a utilizar sólo las clases derivadas (que puede ser, rectángulo, triángulo, pentágono, etc.)

RE: Respuesta de Jeff anterior

clases abstractas no pueden contener funciones miembro virtuales y pueden crear instancias. De hecho, para la sobrecarga de funciones miembro esto es necesario ya que por defecto C ++ no determina el tipo de tiempo de ejecución de una variable, pero cuando se define usando la palabra clave virtual º, lo hará.

Considere este código (nota, descriptores de acceso, mutadores, constructores, etc no se incluyen en aras de la claridad):

class Person{
  int age;

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

class Student: public Person{
  int studentID

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

Ahora cuando se ejecuta este código:

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

sin la palabra clave virtual, solamente la edad sería impresa, no la edad y studentID como se supone que debe ocurrir para la clase Estudiante

(este ejemplo se basa en una muy similar de C ++ para programadores de Java http: //www.amazon.com/Java-Programmers-Mark-Allen-Weiss/dp/013919424X )

@Steven Sudit: usted es completamente correcto, me he olvidado de incluir la herencia real, do! El descriptores de acceso, etc. no se incluyen para mantener las cosas más claras, y he hecho que más evidente ahora. 03/07/09: todo fijo

Esencialmente, virtuals puros se utilizan para crear una interfaz (similar a Java). Esto puede ser usado como un acuerdo entre dos módulos (o clases, o lo que sea) en cuanto a qué tipo de funcionalidad a esperar, sin tener que saber nada acerca de la aplicación de la otra pieza. Esto le permite conectar y reproducir piezas utilizando la misma interfaz sin tener que cambiar nada en el otro módulo que está utilizando la interfaz de fácil.

Por ejemplo:

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

La escuela no tiene que saber cómo configurar el nombre del estudiante, todo lo que necesita saber es cómo obtener el nombre del estudiante. Al proporcionar una interfaz para que un estudiante en práctica y la escuela de usar, no hay un acuerdo entre las dos partes sobre qué funcionalidad es necesaria por la escuela para llevar a cabo su trabajo. Ahora podemos cambiar de entrada y salida diferentes implementaciones de la clase Estudiante todo lo que queremos sin afectar a la escuela (siempre y cuando ponemos en práctica la misma interfaz cada vez).

La idea con clases abstractas es que aún puede tener una variable declarada con ese tipo (es decir, es el tipo estático), pero la variable hace referencia o puntos de hecho a un tipo concreto real (el tipo dinámico).

Cuando se invoca un método en C ++, el compilador tiene que asegurarse de que el método podría ser apoyada sobre ese objeto.

Al declarar la función virtual pura, que están poniendo un "marcador de posición" que el compilador puede utilizar para decir "oh ... Yo sé que todo lo que termina siendo referido por esta variable aceptará esa llamada", porque el hormigón real tipos van a ponerlo en práctica. Sin embargo, usted no tiene que proporcionar una implementación en el tipo abstracto.

Si no declara nada, entonces el compilador no tendría forma efectiva de garantizar que se llevaría a cabo por todos los subtipos.

Por supuesto, si estás preguntando por qué usted quiere hacer una clase abstracta, hay una gran cantidad de información en torno a eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top