返回对此的继承和继承

时间:2012-02-13 17:43:57

标签: c++ templates crtp static-polymorphism

对于一些语法糖,我想返回对this的引用,但是当继承时,该函数应该返回子类的类型:

class base {
  T &operator!() { return *this; }
};
base b; b = !b;

class child : public base {};
child c; c = !c;

由于运算符,我不能只返回指针和dynamic_cast它,它必须是一个参考。

这甚至可能吗?使用decltype(*this)代替T不起作用,auto f()->decltype(*this)也不起作用,因为this(虽然我不明白为什么,在自动情况下)

在Scala中,您可以编写如下内容:

template<typename T> class base {
  T &f() { return *this; }
};
class child : public base<child> {};

但是我的g ++不会接受这个(不确定是不是这个bug还是不在规范中?)

当然有明确的方法,但我想知道使用C ++ 11功能是否可以避免这种情况?

class child : public base {
  child &operator!() { base::operator!(); return *this }
};

2 个答案:

答案 0 :(得分:1)

如果您允许base模板,则可以使用CRTP执行此操作:

template <typename Derived> class Base {
protected:
    Derived& refToThis() {
        return *static_cast<Derived*>(this);
    }
};

请注意这里的额外演员。这样做的原因是,如果你有一个这样的类:

class Subclass: public Base<Subclass> {
    /* ... */
};

然后,如果从该类内部调用refToThis,它将调用基类版本。由于该类继承自Base<Subclass>,因此refToThis的实例化模板将为

    Subclass& refToThis() {
        return *static_cast<Subclass*>(this);
    }

此代码是安全的,因为this指针确实指向Subclass对象。此外,如果派生类没有正确地从static_cast继承,Base将确保转换在编译时失败,因为指针类型将无法转换。

这里需要演员的原因是,如果你只是说

template <typename Derived> class Base {
protected:
    Derived& refToThis() {
        return *this;
    }
};

然后程序中出现类型错误,因为Base本身 Derived,如果您可以将Base&转换为Derived&没有任何检查的operator!你可以打破类型系统。

那说......我根本不会这样做。为此目的重载*this会降低代码的可读性,而只是编写{{1}}是非常惯用的,隐藏它会使代码更难理解。使用所有这些模板机制来避免常见的C ++似乎被误导的东西。如果你在返回参考文献之前做了其他的事情,那很好,但这似乎不是一个好主意。

希望这有帮助!

答案 1 :(得分:0)

请不要这样做。已经有一种方法可以用语言*whatever_pointer_you_want_to_use_this_crazy_operator_upon来完成。创建一种用语言做某事的新方法只会让你未来的维护者感到困惑。你真的想在这里实现 else 吗?