Подтвердить что ты не робот

Каковы преимущества использования чистых виртуальных функций в С++?

Я изучаю С++ в классе прямо сейчас, и я не совсем понимаю чисто виртуальные функции. Я понимаю, что они позже описаны в производном классе, но почему вы хотите объявить его равным 0, если вы просто собираетесь определить его в производном классе?

4b9b3361

Ответ 1

Вкратце, это сделать класс абстрактным, чтобы он не мог быть создан, но дочерний класс может переопределить чистые виртуальные методы для формирования конкретного класса. Это хороший способ определить интерфейс на С++.

Ответ 2

Это заставляет производный класс определять функцию.

Ответ 3

Любой класс, содержащий чистый виртуальный метод, будет абстрактным, т.е. он не может быть создан. Абстрактные классы полезны для определения некоторого основного поведения, которое должны использовать подклассы, но позволяющие (по сути, требующие) подклассы реализовывать абстрактные индивидуально.

Пример абстрактного класса:

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

Ответ 4

Чистые виртуальные методы на С++ - это в основном способ определения интерфейсов, не требуя их реализации.

Ответ 5

Чтобы добавить в ответ Стивена Судата:

"Вкратце, это сделать класс абстрактным, чтобы он не мог быть создан, но дочерний класс может переопределить чистые виртуальные методы для формирования конкретного класса. Это хороший способ определить интерфейс на С++."

Примером этого может быть, если бы у вас был базовый класс (возможно, Shape), который вы используете для определения ряда функций-членов, которые могут использоваться его производными классами, но хотите предотвратить экземпляр формы Shape и заставить пользователей используйте только производные классы (которые могут быть, Rectangle, Triangle, Pentagon и т.д.)

RE: Ответ Джеффа выше

Не абстрактные классы могут содержать виртуальные функции-члены и быть инстанцированными. На самом деле, для перегрузки функций-членов это требуется, поскольку по умолчанию С++ не определяет тип среды выполнения, но при определении с помощью виртуального ключевого слова он будет.

Рассмотрим этот код (примечание, аксессоры, мутаторы, конструкторы и т.д. не включены для ясности):

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

без ключевого слова virtual будет напечатан только возраст, а не возраст и studentID, как предполагается, для класса Student

(этот пример основан на очень похожем для С++ для java-программистов http://www.amazon.com/Java-Programmers-Mark- Allen-Weiss/dp/013919424X)

@Steven Sudit: вы совершенно правы, я пренебрег включением фактического наследования, doh! Аксесуары и т.д. Не включены, чтобы держать вещи яснее, и я сделал это более очевидным сейчас. 3-7-09: все фиксированные

Ответ 6

Представьте, что я хочу моделировать несколько видов фигур, и у всех есть четко определенная область. Я решил, что каждая форма должна наследовать IShape ( "I" для интерфейса), а IShape будет включать метод GetArea():

class IShape {
    virtual int GetArea();
};

Теперь проблема: как мне рассчитать площадь фигуры, если эта форма не переопределяет GetArea()? То есть, какова наилучшая реализация по умолчанию? Круги используют радиус pi * 2, квадраты используют длину ^ 2, параллелограммы и прямоугольники используют основание * высота, треугольники используют 1/2 base * height, rhombuses, pentagons, octagons и т.д., Используя другие формулы.

Итак, я говорю: "Если вы фигура, вы должны определить способ вычисления области, но проклятый, если я знаю, что это будет", определяя метод pure virtual:

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

Ответ 7

По сути, чистые виртуальные машины используются для создания интерфейса (похоже на 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, которые мы хотим, не затрагивая школу (при условии, что каждый раз мы реализуем один и тот же интерфейс).

Ответ 8

Идея с абстрактными классами состоит в том, что вы все равно можете иметь переменную, объявленную с этим типом (т.е. это статический тип), но эта переменная фактически ссылается или указывает на конкретный конкретный тип (динамический тип).

При вызове метода на С++ компилятор должен убедиться, что метод будет поддерживаться на этом объекте.

Объявив чистую виртуальную функцию, вы помещаете "placeholder", который компилятор может использовать, чтобы сказать "о... Я знаю, что все, что в конечном итоге ссылается на эту переменную, будет принимать этот вызов", потому что фактический бетон типы будут реализовывать его. Однако вам не нужно предоставлять реализацию в абстрактном типе.

Если вы ничего не заявляли, тогда у компилятора не было бы эффективного способа гарантировать, что он будет реализован всеми подтипами.

Конечно, если вы спрашиваете, почему вы хотите сделать абстрактную тему, там много информации об этом.