【问题标题】:How to make a member function in an inheritance hierarchy return always the same value?如何使继承层次结构中的成员函数始终返回相同的值?
【发布时间】:2013-03-29 17:56:17
【问题描述】:

我有一个继承层次结构,我想让这个层次结构中的每个类都有一组属性,这些属性是该类特有的,并且在程序运行期间不会改变。例如:

class Base
{
public:
    const std::string getName() const;
    bool getAttribute1() const;
    int getAttribute2() const;
};

现在我希望这些函数始终返回相同的结果。此外,当另一个类继承Base 时,这个类应该有自己的一组属性,并且这个派生类的任何实例都应该有相同的属性。此外,每个类的名称应该是唯一的。

我想知道一种方法,让它尽可能透明和优雅。到目前为止,我已经考虑了两个可以使用的想法:

  1. 制作一些锁系统。

即为这些属性提供设置器,但在多次调用它们时使它们抛出运行时异常。

  1. 让 getter 成为纯虚拟的。

在这种情况下,函数的结果不会存储在对象本身中。这会模糊地表明结果取决于动态类型。

这两个想法听起来都非常糟糕,所以我需要你的帮助。

我是 C++ 新手,但我知道有很多习语和模式可以解决像这样的一般问题。你知道吗?

【问题讨论】:

  • 你需要更好地思考你想要做什么(当然要提到它是什么)。纯虚拟到底有什么问题?为什么听起来很糟糕?
  • 我正在尝试建立遗传算法的层次结构。它们有很多共同点,因此我将它们表示为对象,并且每个算法都应该有一个唯一的名称。虚函数的问题在于,它们总是返回与例如const 静态成员。

标签: c++ design-patterns


【解决方案1】:

我有一个继承层次结构,我想让这个层次结构中的每个类都有一组属性,这些属性是该类特有的,并且在程序运行期间不会改变

那么,只需将相应的值作为参数提供给类构造函数,不要在公共接口上公开任何 setter 方法。这将确保值在对象的整个生命周期内保持不变。

为了防止可能发生的错误会改变您类的成员函数(当然可以访问私有数据)中这些数据成员的值,请将这些数据成员设为const。请注意,这将强制您在构造函数的初始化列表中初始化这些成员。

class Base
{
public:
    // Forwarding constructor (requires C++11)
    Base() : Base("base", true, 42) { }
    const std::string getName() const { return _s; }
    bool getAttribute1() const { return _a1; }
    int getAttribute2() const { return _a2; }

protected:
    // Constructor that can be called by derived classes
    Base(std::string s, bool a1, int a2)
    : _s(s), _a1(a1), _a2(a2) { }

private:
    const std::string _s;
    const bool _a1;
    const bool _a2;
};

然后派生类将使用适当的参数构造基础子对象:

class Derived : public Base
{
public:
    // Provide the values for the constant data members to the base constructor
    Derived() : Base("derived", false, 1729) { }
};

这样您就不会产生虚函数调用的开销,并且您不必为派生类中的每个成员重写类似的虚函数。

【讨论】:

    【解决方案2】:

    将它们设为虚拟并硬编码函数应返回的结果:

    class Base
    {
    public:
        virtual const std::string getName() const { return "BaseName"; }
        virtual bool getAttribute1() const { return whatEverAttributeValueYouWant; }
        virtual int getAttribute2() const { return attributeValueHere; }
    };
    
    class Derived : public Base {
    public:
        virtual const std::string getName() const { return "DerivedName"; }
        virtual bool getAttribute1() const { return whatEverOtherAttributeValueYouWant; }
        virtual int getAttribute2() const { return otherAttributeValueHere; }
    };
    

    如果您想描述而不是对象,请使用(种类)特征:

    template<class T> struct AttributeValues;
    
    template<> struct AttributeValues<Base> {
        static const std::string name () { return "BaseName"; }
    };
    
    template<> struct AttributeValues<Derived> {
        static const std::string name () { return "DerivedName"; }
    };
    
    //...
    
    auto nameBase = AttributeValues<Base>::name ();
    auto nameDerived = AttributeValues<Derived>::name ();
    

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 2014-07-31
      • 1970-01-01
      • 2019-12-10
      • 2021-08-23
      • 2012-08-31
      • 1970-01-01
      • 2014-12-22
      相关资源
      最近更新 更多