c++ - 从祖先的方法和构造函数调用后代的方法

标签 c++ c++11 inheritance parameters constructor

接下来的代码展示了类参数包装器,它允许通过 getter 和 setter 访问底层类。简化版:

template<typename T>
class Parameter
{
public:
    typedef T value_type;
    typedef Parameter<T> Type;
protected:
    T value_;
public:
    Parameter() { this->value_ = this->default_value(); }
    Parameter(T&& val) { this->set(std::forward<T>(val)); }
    Parameter(const T& val) { this->set(std::forward<T>(val)); }
    virtual ~Parameter() {};

    // Get
    T& get() { return this->value_/*this->getter()*/; }
    operator T&() { return this->get(); }

    // Set
    Type& set(T&& val)
    {
        std::cout << "T&& setter called with " << val << std::endl;
        value_ = this->setter(std::forward<T>(val));
        return *this;
    }
    Type& set(const T& val)
    {
        std::cout << "constT& setter called with " << val << std::endl;
        value_ = this->setter(std::forward<const T>(val));
        return *this;
    }
    Type& operator=(T const& val) { return this->set(val); }
    Type& operator=(T&& val) { return this->set(val); }

    virtual T setter(T const& val) { return val; }

    virtual const T& default_value()
    {
        static const T default_value_{};
        return default_value_;
    };
};

使用:

int main()
{
    struct IncrementorPar : Parameter<int>
    {
        using Parameter::Parameter;  //todo HIDE
        using Parameter::operator=;  //todo HIDE
        virtual int setter(int const& val) { return val + 1; }
        virtual const int& default_value(){ return -1; };
    } in1(1), in2 = 2, int0;
    //assert(int0==int0.default_value());  //FAIL
    //assert(int0==-1);  //FAIL
    //assert(in1 == 2);  //FAIL
    //assert(in2 == 3);  //FAIL
    auto *pi1 = new IncrementorPar(2);
    //assert(*pi1==3);  //FAIL
    pi1->set(2);
    assert(*pi1==3);
    *pi1 = 33;}
}

如何从祖先的构造函数调用后代的方法 setter()default_value()
如何隐藏 using

最佳答案

这不是一个优雅的解决方案,但是......

您可以使用 init() 函数推迟 value_ 的初始化。

有点像

template<typename T>
class Parameter
{
private:
    bool  toInit { true };
    bool  initWithVal;
    T     valInit;

    void init ()
     {
       if ( initWithVal )
          this->set(valInit);
       else
          value_ = this->default_value();

       toInit = false;
     }

public:
    typedef T value_type;
    typedef Parameter<T> Type;
protected:
    T value_;
public:
    Parameter() : initWithVal{false} { }
    Parameter(T&& val) : initWithVal{true}, valInit{std::move(val)} { }
    Parameter(const T& val) { this->set(std::forward<T>(val)); }
    virtual ~Parameter() {};

    // Get
    T& get() { if ( toInit ) init(); return this->value_/*this->getter()*/; }
    operator T&() { return this->get(); }

    // Set
    Type& set(T&& val)
    {
      toInit = false;
      std::cout << "T&& setter called with " << val << std::endl;
      value_ = this->setter(std::forward<T>(val));
      return *this;
    }
    Type& set(const T& val)
    {
      toInit = false;
      std::cout << "constT& setter called with " << val << std::endl;
      value_ = this->setter(std::forward<const T>(val));
      return *this;
    }
    Type& operator=(T const& val) { return this->set(val); }
    Type& operator=(T&& val) { return this->set(val); }

    virtual T setter(T const& val) { return val; }

    virtual const T& default_value()
    {
      std::cout << "base default value\n";
        static const T default_value_{};
        return default_value_;
    };
};

关于c++ - 从祖先的方法和构造函数调用后代的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39710542/

相关文章:

c++ - 类定义之外的部分模板特化定义

inheritance - Go - 如何明确声明一个结构正在实现一个接口(interface)?

c++ - 线性多维容器

c++ - boost::serialization - 是否有一种可移植的方式来二进制序列化 std::wstrings?

c++ - 将指针转换为指向多维数组的指针

c++ - shrink_to_fit 是将容量 a `std::vector` 减小到其大小的正确方法吗?

c++ - 如何在 Bazel 中忽略来自外部 C++ 依赖项 header 的警告

c++ - 将迭代器取消引用到临时范围时出现非指针操作数错误

c++ - 从派生**转换为基础**

javascript - 了解 Javascript super 方法模拟代码