确保派生类构造函数必须调用特定的基类方法

时间:2012-12-09 13:40:39

标签: c++ inheritance c++03

在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类在客户端代码中,我无法控制。

3 个答案:

答案 0 :(得分:9)

如果派生类构造函数必须调用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 :(得分: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的成员,也可以是执行计算的任何函数。

答案 2 :(得分:0)

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