2012-02-13 45 views
2

对于一些语法糖我想引用返回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

请不要以改变其基本含义的方式重写操作符。这是一个非常糟糕的主意,会导致混乱和错误。 – 2012-02-13 18:38:51

+0

在这种情况下,它是一个DSL的东西,我实际上使用&&,即使它不返回一个布尔,它的语义意思是“和” – pascal 2012-02-13 20:53:48

回答

1

可以使用CRTP要做到这一点,如果你允许做base模板:

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非常地道,隐藏它会使你的代码难以理解。使用所有这些模板机制来避免常见的C++似乎被误导了。如果你在返回引用之前做了其他事情,那么这看起来不是一个好主意。

希望这会有所帮助!

+0

谢谢,我的代码中有一些干扰导致在类的子类:public base 'line,我担心这在C++中是不可能的。 – pascal 2012-02-13 21:01:24

0

请不要这样做。已经有一种方法可以使用该语言,*whatever_pointer_you_want_to_use_this_crazy_operator_upon。在语言中创建一种新的方式只会混淆你未来的维护者。有什么其他你真的想在这里实现?

+0

我真正想要做的是'a << b << c << d',其中'<<'运算符在基类中定义并且被继承,但是我需要左侧的子类型,与ostream不同 – pascal 2012-02-13 20:57:14