可以在没有C ++的纯虚函数的情况下实现抽象类吗?

时间:2013-07-03 18:10:56

标签: c++ abstract-class pure-virtual

我想过使用受保护的构造函数,但它无法完全解决目的,因为继承它的类能够实例化基类。

对于私有构造函数,派生类也不会被实例化。

所以,任何合适的技术都会受到赞赏。

4 个答案:

答案 0 :(得分:3)

目前还不清楚你真正要求的是什么。所以让我试着澄清一些观点:

纯虚函数可以有定义

如果您担心要为基础中的所有虚拟函数提供定义,则可以提供纯虚函数的定义,它们可用于静态调度。

受保护授予您对基础子对象的访问权限,而不是对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
   }
};

答案 1 :(得分:1)

抽象类的定义是至少有一个纯虚函数的定义(virtual function-signature = 0;没有它们就不能创建抽象类。

答案 2 :(得分:1)

  

在C ++中没有纯虚函数可以实现抽象类吗?

如果您从 Static Polymorphism 选择观点,就可以

抽象基类只是缺少派生类中接口方法的默认方法实现。

此外,您可以对这些CRTP基类模板使用受保护的构造函数,以要求继承实例化。

<强>更新
我找到了一个很好的幻灯片,全面地解释了static vs dynamic polymorphism。每种技术都有它的优点和缺点以及某些使用领域,另外你可以混合使用这两种技术(当然是明智的)。

详细说明一点,我将举例:

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

以下示例显示上面介绍的模式强制抽象类和继承类(模板参数)之间的“Is a”关系

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; 

答案 3 :(得分:0)

我在书中看到了它 抽象类是一个专门用作基类的类。抽象类包含至少一个纯虚函数。您可以在类声明中的虚拟成员函数声明中使用纯说明符(= 0)声明纯虚函数。