考慮一個封閉類層次結構如下述:減少對基礎樣板衍生委託在非虛擬多態類
class B {...};
class D1 final : public B {...};
class D2 final : public B {...};
凡B
是一個抽象的基類和D1
和D2
是它的派生類。
由於實現約束或設計,沒有這些類的具有任何virtual
方法,但成員函數上B
在D1
具有不同的實現並D2
簡單地通過使衍生的運行時檢查委託給實際最派生的類型類型,如下所示:
class B {
bool isD1;
protected:
B(bool isD1) : isD1{isD1} {}
public:
std::string to_string() {
return isD1 ? static_cast<D1*>(this)->to_string() : static_cast<D2*>(this)->to_string();
}
}
class D1 final : public B {
public:
D1() : B(true) {}
std::string to_string() { // D1 specific implementation ... }
}
class D2 final : public B {
public:
D2() : B(false) {}
std::string to_string() { // D2 specific implementation ... }
}
上。這裏B
的to_string
方法只檢查的B
最派生類型是D1
D2
或並調用適當的方法(也使用C稱爲to_string
ASES)。
很酷。
現在想象有另外10種方法,如B::to_string
。我可以在C++ 11中做什麼來減少B
中的委託樣板文件,而不使用宏?
在C++ 14它似乎是一個合理的做法是一個通用的代理機制,如:
class B {
...
template <typename F>
auto delegate(F&& f) -> decltype(f(D1{})) {
return isD1 : f(*static_cast<D1*>(this)) : f(*static_cast<D2*>(this));
}
std::string to_string() {
return delegate([](auto&& b){ return b.to_string(); });
}
}
這裏[](auto&& b){ return b.to_string(); }
通用拉姆達作品是否最終通過了D1
或D2
(因爲兩者具有to_string
方法) 。在C++ 11中,我沒有看到用同樣簡潔的方式表達這一點。
任何想法?當然,你可以使用宏來複制一個非泛型的宏,並將它傳遞給一個雙參數的delegate
方法(對D1
和D2
採用不同的函子),但我想避免使用宏。
這裏關閉意味着該組B
派生類的固定和在運行時是已知的。
摘要在概念但不是在 「純virtual
」 感。那就是這個類不應該直接實例化 - 唯一有意義的整個對象是它的派生類。各種構造函數都製作爲protected
來執行此操作。
我是否正確拒絕了基於預處理器宏的解決方案? – lockcmpxchg8b
@ lockcmpxchg8b - 正確。事實上,我已經在使用這樣的解決方案,因爲編寫'DELEGATE(x)'宏很容易,所以'DELEGATE(std :: string,to_string)'簡單地擴展到'B :: to_string()'實現如上所示,然後一些其他的宏來處理帶參數的函數等。 – BeeOnRope
@BeeOnRope - 我完全誤解了這個問題;抱歉。 – max66