【问题标题】:Ensure derived class constructor must call specific base class method确保派生类构造函数必须调用特定的基类方法
【发布时间】:2012-12-09 13:40:39
【问题描述】:

在 C++(03) 类中,我有一个成员变量,必须在对象构造期间为其赋值。但是,只有派生类可以计算所需的值。正如这篇文章Does C++ require you to initialize base class members from its derived class? 中所讨论的,我知道派生类不能初始化基类成员,但对我来说,赋值就足够了。

因此,我在基类中提供了一个分配值的方法,但我不知道如何强制派生类调用它。下面的示例代码说明了这一点。

class Base {
public:
    Base() {}
    setFoo(unsigned inFoo) { foo = inFoo; }
private:
    unsigned foo;
};

class Derived : public Base {
    Derived() : Base() { 
        unsigned desired = ... // do calculations to get the desired value
        setFoo(desired);  // --> how to ensure that derived class calls this?
    }
};

foo 然后被其他几个基类方法使用。即使我在setFoo() 中设置了一个“标志”,也没有可以检查它的“后构造函数”方法。在使用foo 的基类中还有其他几种方法。我可以在那里检查,但这样做太繁琐、容易出错且效率低下。

如果之前有人问过这个问题,我深表歉意。在通过搜索“确保派生类构造函数必须调用特定的基类方法”和“强制派生类分配基类成员”来询问之前,我确实尝试在这里找到它。我遇到了一些有用的帖子 How can I initialize a const variable of a base class in a derived class' constructor in C++?Force a Derived Class to use the Constructor of the Base Class ,但不幸的是它们没有解决我的问题。

您能否建议我一种合适的方法来解决这种情况?编译时检查解决方案是可取的,但如果不可能,运行时检查也会有所帮助。虽然我不能使用 C++11 来解决我的问题,但我也很乐意学习任何 C++11 解决方案。感谢您的考虑。

编辑当然,将其记录为要求也是一种选择,但我想了解是否有程序化解决方案。

Edit2 我同意应该在构造函数参数中传递值的答案,如果我必须从头开始编写Base,我不会要求这种方法。问题是由于遗留原因,Base 已经有几个构造函数参数 (9),我希望通过将它们“卸载”到构造函数主体来避免添加更多参数 (3)。但从长远来看,代码必须重构。

Edit3 抱歉编辑了这么多。我可以随意修改Base 类,但Derived 类在客户端代码中,我无法控制。

【问题讨论】:

    标签: c++ inheritance c++03


    【解决方案1】:

    如果派生类的构造函数必须调用setFoo(),那么我认为这是一个设计问题。最好设计基类,使其构造函数将期望的值作为参数,并让派生类将计算值传递为:

    class Base {
    public:
        Base(unsigned int foo) : m_foo (foo) {}  //define this constructor
    private:
        unsigned int m_foo; //member data
    };
    
    class Derived : public Base {
        Derived() : Base(computeValue()) 
        { 
        }
    private:
        static unsigned int computeValue() //it may take argument(s)
        {
            unsigned int desired = ... //do calculations to get the desired value
            return desired;
        }
    };
    

    【讨论】:

    • +1 但是对于成员变量和形式参数使用相同的名称是不必要的混淆。 请解决这个问题
    • @Cheersandhth.-Alf:完成。 :-)
    • 感谢您的回复。我同意这不是一个好的设计,但问题是由于遗留原因,基类构造函数有几个参数,我需要扩展它。我希望找到一种方法来避免添加更多参数。从长远来看,必须重构代码。我想我应该在问题本身中说明这一点,我很抱歉遗漏了这一点。
    • @RoeeGavirel:构造函数无论如何都可以这样做。而且,这只是一个基本的想法。如果它需要是非静态成员,那么 OP 可以随时制作,但这也不是更好的主意,因为成员函数最终可能会访问其他 uninitialized 成员数据,因为对象未完全建。如果是这样,那么它是未定义的行为。
    • @ap:“我希望找到一种方法来避免添加更多参数”——这是一个不同的 SO 问题。单独发布。
    【解决方案2】:

    如果一个对象的构造需要一个值,它应该是构造函数的参数。

    class Base {
    public:
        Base(unsigned inFoo) { setFoo(inFoo); }
        setFoo(unsigned inFoo) { foo = inFoo; }
    private:
        unsigned foo;
    };
    
    class Derived : public Base {
        Derived() : Base(compute_desired()) { }
    
    };
    

    这里的compute_desired 可以是Derived 的成员,也可以是任何进行计算的函数。

    【讨论】:

      【解决方案3】:

      我认为不可能强制派生类在其构造函数中调用基类方法。您可以通过其他响应中的技术强制实现/调用,但据我所知,绝对确保它在 Derived 的构造函数中完成是不可能的,除非可以修改基类

      【讨论】:

      • 基类可以修改,问题中没有说清楚很抱歉。
      猜你喜欢
      • 2011-03-05
      • 2016-07-19
      • 2010-09-21
      • 2018-07-16
      • 1970-01-01
      • 2018-07-21
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      相关资源
      最近更新 更多