对于一些语法糖,我想返回对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 }
};
答案 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 吗?