【问题标题】:C++: design adviceC++:设计建议
【发布时间】:2025-12-15 08:40:02
【问题描述】:

我需要一些关于我的类层次结构设计的建议。我当前设计的“骨架”是

template <class X>
class BASE {
  public:
    virtual void f() {
        x_.f2(m_);
    }

    void g() {
        /* do stuff here*/
        x_.g();
    }

    /* more member functions here*/

  protected:
    X x_;
    int m_;
};

template <class X>
class DERIVED : BASE<X> {
    public:
      virtual f() override {
         x_.f1();
      }

     protected:
     using BASE<X>::x_;
     using BASE<X>::m_;
};

最后我还有两个这样的课程

struct X1 {
  void f1();
  void g();
};

struct X2 : X1 {
void f2(int m);
};

我希望能够创建DERIVED&lt;X1&gt; 的实例。为此,编译器将首先创建BASE&lt;X1&gt; 的实例,在这种情况下,它会抱怨 X1 没有成员函数 f2(尽管实际上它永远不会被调用,因为调用函数 f() 是虚拟的)。

我知道这是一个糟糕的设计,因为为了有一个模板类,模板参数必须具有相同的接口。在我的例子中,X1 和 X2 有一个共同的接口,但 X2 有更多的功能,这就产生了上述问题。我知道我可以在 X1 中创建一个什么都不做的 f2 函数,但理想情况下我想避免这种情况。

我欢迎任何关于改进设计的建议。提前致谢!

【问题讨论】:

  • 在设计时,我建议从设计要解决的问题的具体示例开始。你没有提到任何具体的例子,所以很难给出任何设计建议。

标签: c++ templates inheritance virtual


【解决方案1】:

避免从具体类派生。将接口/ABC 提升到顶部,使所有具体类离开。这是针对多种设计困难的一般建议。

在你的特定情况下,而不是这个:

             BASE    // concrete
              | 
           DERIVED

使用这个:

             BASE   // fully abstract
            /   \
BASIC_DERIVED    ADVANCED_DERIVED

现在fBASE 中是纯虚拟的,一切正常。

【讨论】:

    【解决方案2】:

    第一个建议是不要使用受保护的属性。是打破封装。

    第二个建议是使virtual void f()=0 成为纯虚拟而无需实现。在这种情况下,派生类不会出错。

    【讨论】: