C : вызов абстрактного метода внутри абстрактного класса

#c #abstract-class #virtual

#c #абстрактный класс #виртуальный

Вопрос:

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

Вот что я хочу сделать :

 class abstractClass { 
     public:
     virtual void abstractMethod() = 0 ;
     void nonAbstractMethod();
}
  

в .cpp :

 void abstractClass::nonAbstractMethod() {
     abstractClass::abstractMethod();

     /* ... */

}
  

Возможно ли это в c ?

Проблема здесь в том, что nonAbstracMethod не является статическим, поэтому я не могу вызвать его без экземпляра object . Но это абстрактный класс! Я не могу создать его экземпляр… Как я могу справиться с этим?

Я часто делаю это на Java, но я не нашел, как в c …

Комментарии:

1. Это просто головоломка, или вы пытаетесь что-то сделать ?

2. Просто не указывайте его именем типа: abstractMethod();

3. Просто вызовите метод без квалификатора classname: abstractMethod();

4. Невозможно вызвать абстрактный метод, потому что у него нет никакой реализации. Зачем вам это нужно? Что должен делать абстрактный метод?

5. @AngeloDM: это верно только для конструкторов и деструкторов

Ответ №1:

Конкретные подклассы предоставят свою версию abstractMethod() . При вызове виртуального механизма nonAbstractMethod() вызова с экземпляром конкретного подкласса abstractMethod() будет вызвана правильная реализация. То есть, если вы не определяете метод с именем типа (что вы можете сделать, если вы также предоставляете реализацию в abstractClass *).

Вы должны помнить, что деструктор abstractClass должен быть виртуальным, поэтому правильный вызывается, когда объект удаляется с помощью abstractClass указателя.

Кроме того, вы должны знать, что функции-члены статически связаны в конструкторе деструкторах. В противном случае вы бы вызывали методы, ожидающие части объекта, которые еще не созданы или уже уничтожены.

Это объектно-ориентированное программирование 101

* Да, чисто виртуальные функции могут иметь реализацию.

Комментарии:

1. @MooingDuck, я уловил твой намек?

2. У меня есть деструктор / конструктор. Я не включил это в свой код, чтобы было понятно. Извините. Это был просто пример, мой код более сложный.

3. когда я ничего не пишу перед abstactMethod() , он его не распознает :/ Я уже пробовал это.

4. @Kostinen, есть ли пропуск ; после определения класса в вашем фактическом коде кода? Потому что после его исправления он строится без сучка и задоринки ideone.com/9tPcJE

5. Спасибо за ваш ответ 🙂 Я не пробовал код, который я привел здесь для примера. Мой код более сложный и был в порядке, когда я просто использовал один абстрактный метод, но я хочу разложить на множители некоторый код в неабстрактном методе, чтобы мне не нужно было помнить, чтобы поместить это в каждый унаследованный класс (или кто-то, кто хочет создать класс, унаследованный из абстрактного класса). Итак, мой код в порядке! (У меня 5 лет кодирования: я бы не задавал этот вопрос, если бы это было просто для «;» 🙂 ).

Ответ №2:

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

И ваш синтаксис будет просто:

 void abstractClass::nonAbstractMethod() {
     abstractMethod();
    /* ... */
}
  

Итак, это будет выглядеть так:

 class ConcreteClass : public abstractClass {
  virtual void abstractMethod() { //do something 
  }
};

int main() {
  abstractClass *a = new ConcreteClass();
  a->nonAbstractMethod();
  return 0;
}
  

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

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

Комментарии:

1. Было бы неплохо добавить предложение о конструкторах / деструкторах

Ответ №3:

Я часто делаю это на Java, но я не нашел, как в c …

Это то, что я не совсем понимаю в вашем вопросе. Если вы знаете, как это сделать на Java, то в чем именно проблема в C ? Все, что вам нужно сделать, это добавить виртуальный деструктор и подумать о том, чтобы сделать абстрактный метод закрытым (а не защищенным, как в Java).

Java:

 public abstract class Example {
    protected abstract void abstractMethod();
    public void nonAbstractMethod() {
        abstractMethod();
    }
}
  

C :

 class Example {
private:
    virtual void abstractMethod() = 0;
public:
    void nonAbstractMethod() {
        abstractMethod();
    }
    virtual ~Example() {}
};
  

Подсказка: проведите некоторое исследование в Google по «Шаблону проектирования метода шаблона» или «Идиоме невиртуального интерфейса».

Комментарии:

1. Это именно то, что я уже пробовал! Итак, хорошо, мы можем сделать это на c , я рад 🙂 Возможно, проблема в чем-то другом.

2. частный абстрактный метод , на самом деле?

3. @Yola: Да. Абстрактность функции относится к ее реализации; спецификатор доступа относится к тому, как она вызывается. Это две разные проблемы. К сожалению, большинство других языков смешивают их и запрещают частные абстрактные методы, но C делает это правильно.