Можно ли реализовать абстрактный класс без чистых виртуальных функций в C++?

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

Что касается приватного конструктора, производные классы также не будут созданы.

Таким образом, любая подходящая техника будет оценена по достоинству.


person Sankalp    schedule 03.07.2013    source источник
comment
Если нет хотя бы одной чистой виртуальной функции, то это не абстрактный класс.   -  person Captain Obvlious    schedule 03.07.2013
comment
Что вы на самом деле пытаетесь сделать?   -  person Beta    schedule 03.07.2013
comment
Я пытался имитировать эффект чистой виртуальной функции в классе без виртуальной виртуальной функции в классе!   -  person Sankalp    schedule 03.07.2013
comment
Почему вы пытаетесь добиться этого? Вы хотите, чтобы производные классы реализовывали функцию, но в то же время предоставляли реализацию в базовом классе? Вы должны отредактировать свой вопрос и уточнить, что вы пытаетесь сделать, почему вы пытаетесь это сделать и, если возможно, пример кода того, как вы хотите, чтобы это было реализовано.   -  person Captain Obvlious    schedule 03.07.2013


Ответы (4)


Непонятно, что вы на самом деле просите. Итак, позвольте мне попытаться прояснить некоторые моменты:

Чисто виртуальные функции могут иметь определения

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

Защищено предоставляет доступ к вашему базовому подобъекту, а не ко всем экземплярам base

Существует распространенное заблуждение, что protected позволяет определенному производному типу обращаться к любому экземпляру base. Это неправда. Ключевое слово protected предоставляет доступ к подобъекту base в производном типе.

class base {
protected: base() {}
};
class derived : public base {
   derived() : base() {         // fine our subobject
      base b;                   // error, `b` is not your subobject
   }
};
person David Rodríguez - dribeas    schedule 03.07.2013
comment
@Sankalp: Это не говорит о том, что вы пытаетесь сделать, а только о том, какой у вас был подход к этому. Что вы хотите сделать, чтобы подделать абстрактные классы? - person David Rodríguez - dribeas; 03.07.2013

Определение абстрактного класса — это такое, которое имеет хотя бы одну чистую виртуальную функцию (virtual function-signature = 0; Вы не можете создать абстрактный класс без них.

person Jashaszun    schedule 03.07.2013
comment
@g-makulik - это определение языка C++. - person Pete Becker; 04.07.2013
comment
@PeteBecker Но абстрактный класс - это просто концепция (неопределяемый класс). Посмотрите на концепции статического полиморфизма, и вы увидите, что можно создавать абстрактные классы без использования чисто виртуальных функций. - person πάντα ῥεῖ; 04.07.2013
comment
@PeteBecker Я провел небольшое исследование и вижу, что вы, кажется, правы в отношении официальных определений термина «абстрактный класс» в сочетании с языком C ++ (всегда объясняется как 'класс, имеющий хотя бы одну чистую абстрактную функцию определение'). Но я по-прежнему считаю, что класс базового шаблона CRTP, который не предоставляет реализацию по умолчанию для определенного метода интерфейса, может/должен считаться абстрактным классом. - person πάντα ῥεῖ; 04.07.2013

Можно ли реализовать абстрактный класс без чистых виртуальных функций в C++?

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

В абстрактном базовом классе просто отсутствовала бы реализация метода по умолчанию для метода интерфейса из производного класса.

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

ОБНОВЛЕНИЕ:
я нашел хорошее слайд-шоу, объясняющее статический и динамический полиморфизм всесторонне. Каждая техника имеет свои плюсы и минусы и определенные области применения, кроме того, вы можете комбинировать обе техники (разумеется, с умом).

Чтобы немного уточнить, я приведу образец:

template<class Derived>
class AbstractBase
{
public:
    // Equivalent for a pure virtual function
    void foo()
    {
        // static_cast<> enforces an 'Is a' relation from Derived to AbstractBase
        static_cast<Derived*>(this)->fooImpl();
    }

    // Equivalent for simple virtual function (overidable from Derived)
    void bar()
    {
        static_cast<Derived*>(this)->barImpl();
    }

    // Default implementation for any call to bar()
    void barImpl()
    {
    }

protected:
    AbstractBase() {}
};

// Compilation will fail, since ConcreteClass1 doesn't provide 
// a declaration for fooImpl()
class ConcreteClass1
: public AbstractBase<ConcreteClass1>
{
}


// Compiles fine
class ConcreteClass2
: public AbstractBase<ConcreteClass2>
{
public:

    void fooImpl()
    {
        // Concrete implementation ...
    }
}

В следующем примере показано, что представленный выше шаблон обеспечивает связь «Является» между абстрактным классом и наследующим классом (параметр шаблона).

class ConcreteClass3
{
public:
    void fooImpl()
    {
        // Concrete implementation ...
    }
}   

// Instantiation will fail, because 
// * the constructor is protected
// * at least the static cast will fail
AbstractBase<ConcreteClass3> instance; 
person πάντα ῥεῖ    schedule 03.07.2013

Я прочитал это в своей книге. Абстрактный класс — это класс, специально предназначенный для использования в качестве базового класса. Абстрактный класс содержит по крайней мере одну чисто виртуальную функцию. Вы объявляете чистую виртуальную функцию, используя чистый спецификатор (= 0) в объявлении виртуальной функции-члена в объявлении класса.

person priyanka    schedule 17.12.2014