【问题标题】:Implementing a class hierarchy properly正确实现类层次结构
【发布时间】:2015-05-14 23:09:22
【问题描述】:

假设我有一个接口层次结构:

class A
{
   virtual void commonFunc() = 0;
};

class B1 : public A
{
   virtual void b1SpecificFunc() = 0;
};

class B2 : public A
{
   virtual void b2SpecificFunc() = 0;
};

接口 A 的存在只是为了避免重复 commonFunc() 函数。

现在,如果我想实现它以便拥有 2 个可实例化的类 ImplB1 和 ImplB2,我可以这样做:

class ImplA
{
   virtual void commonFunc();
};

class ImplB1 : public ImplA
{
   virtual void b1SpecificFunc();
};

class ImplB2 : public ImplA
{
   virtual void b2SpecificFunc();
};

这样做的问题是它使 ImplA 可实例化,这是我不希望的。我只希望 ImplB1 和 ImplB2 是可实例化的,因为 ImplA 是抽象的东西,它的存在只是为了共同实现公共功能。

请问我该如何设计?谢谢。

【问题讨论】:

  • 使 ImplA 的构造函数受保护和/或不从 ImplA 继承并使用组合来共享 commonFunc 的实现。
  • @KristianDuske:或者只是将commonFunc 排除在整个类层次结构之外。不知道更多细节很难说。
  • 作曲+1。为什么不将构造函数设为私有但成为 Bs 的朋友并将其实例化为 Bs 中的成员?

标签: c++ class inheritance interface implementation


【解决方案1】:

您可以执行以下操作。另外,这里有一个关于这个的 SO question/answer

注意:虽然我在回答你可以这样做的问题,但我并不是说这是你应该这样做

代码

#include <iostream>

class A
{
public:
    virtual void commonFunc() = 0;
};


void A::commonFunc() // Pure virtual but implemented anyway
{
    // Derived classes can explicitly opt-in to this implementation
    std::cout << "A::commonFunc()\n";
}

class B1 : public A
{
public:
    virtual void b1SpecificFunc() = 0;
};

class B2 : public A
{
    virtual void b2SpecificFunc() = 0;
};

class ImplB1 : public B1
{
public:
    // This function must be implemented because its declared pure virtual
    virtual void commonFunc()
    {
        // Can override the behavior if desired...
        A::commonFunc(); // Explicitly use default implementation
    }

    virtual void b1SpecificFunc()
    {
        std::cout << "b1SpecificFunc()\n";
    }
};

class ImplB2 : public B2
{
public:
    // This function must be implemented because its declared pure virtual
    virtual void commonFunc()
    {
        // Can override the behavior if desired...
        A::commonFunc(); // Explicitly use default implementation
    }

    virtual void b2SpecificFunc()
    {
        std::cout << "b2SpecificFunc()\n";
    }
};

int main()
{
    //A a; // Won't compile (as expected/desired)
    ImplB1 b1;
    ImplB2 b2;

    b1.commonFunc();
    b1.b1SpecificFunc();

    b2.commonFunc();
    b2.b2SpecificFunc();

    return 0;
}

输出

A::commonFunc()
b1SpecificFunc()
A::commonFunc()
b2SpecificFunc()

【讨论】:

    【解决方案2】:

    接口 A 的存在只是为了避免重复 commonFunc() 函数。

    您当然是要避免重复其声明,不是吗?

    class ImplA
    {
       virtual void commonFunc();
    };
    

    这应该是:

    class ImplA : public A
    {
       virtual void commonFunc();
    };
    

    我猜重点是ImplA 实际上有一个commonFunc 的实现。所以为了这个答案的简洁,让我们把它放到类定义中:

    class ImplA : public A
    {
       virtual void commonFunc() {} // implementation
    };
    

    这样做的问题是它使 ImplA 可实例化。

    只需将ImplA 的析构函数设为纯虚拟即可:

    class ImplA : public A
    {
    public:
       virtual ~ImplA() = 0 {}
    
    private:
       virtual void commonFunc() {}
    };
    

    即使在派生类的函数内部,这也会阻止实例化。例如,以下将产生编译器错误:

    class ImplB1 : public ImplA
    {
    public:
       virtual void b1SpecificFunc()
       {
           ImplA a; // error, cannot instantiate abstract class
       }
    };
    

    事实上,你甚至不能在它自己的函数中实例化这个类:

    class ImplA : public A
    {
    public:
       virtual ~ImplA() = 0 {}
    
    private:
       virtual void commonFunc()
       {
           ImplA a; // error, cannot instantiate abstract class
       }
    };
    

    但说真的,这一切似乎都过度设计。也许您真正需要的是使commonFunc 成为A 的非虚拟保护函数,然后派生类可以在需要时调用。

    或者commonFunc 可能只是一个独立的效用函数

    【讨论】:

    • virtual ~ImplA() = 0 {} 这是什么魔法?!
    • 感谢您的帮助。是的,它可能看起来有点过于复杂,但我想到的所有解决方案都有一些脏东西。我不确定你所说的独立实用程序函数是什么意思,但这个函数实际上是两个子类共有的几个函数。
    • @KristianDuske:嗯,它是一个带有实现的纯虚拟析构函数。析构函数需要一个实现。归根结底,= 0 只是表示“这个成员函数的类是抽象的”,而不是“这个函数无法实现”。
    • @Virus721:这取决于commonFunc 的实际作用。在 C++ 中,您不必将每个函数都放入一个类中。使函数完全独立通常更容易(并且对于更简洁的 OOP 方法来说更好!)。
    • 感谢您的解释,我不知道这是可能的。
    猜你喜欢
    • 2014-01-30
    • 2017-02-16
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多