2012-02-13 75 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