由於返回類型問題,我們不能直接製作operator++(int)
virtual
。通常的建議是應用好奇地命名Curiously Recurring Template Pattern
,這是我實現盡我微薄的理解如下:是否可以完全模擬虛擬運算符++(int)?
// abstract numeric type
template <typename T>
class A {
public:
virtual T& operator++() = 0;
virtual T get() const = 0;
virtual string toString() const = 0;
virtual T operator++(int) {
T old(this->get());
++*this; // calls operator++() from derived class
return old;
}
friend ostream& operator<<(ostream& os, const A& a) {
return os << a.toString();
}
virtual ~A() = 0;
};
// signed numeric type
class S : public A<S> {
public:
S(long l) : m_l(l) {}
virtual S get() const { return m_l; }
virtual string toString() const { return to_string(m_l); }
virtual S& operator++() { // no wrapping, caps at LONG_MAX
if (m_l < LONG_MAX)
++m_l;
return *this;
}
private:
long m_l;
};
// unsigned numeric type
class U : public A<U> {
public:
U(unsigned long ul) : m_ul(ul) {}
virtual U get() const { return m_ul; }
virtual string toString() const { return to_string(m_ul); }
virtual U& operator++() { // no wrapping, caps at ULONG_MAX
if (m_ul < ULONG_MAX)
++m_ul;
return *this;
}
private:
unsigned long m_ul;
};
大量的重複代碼,但至少它允許像下面運行,其結構絕對是一個開始:
template <typename T>
void pinc(A<T>& a) {
cout << a++ << ' ' << a << endl;
}
int main() {
S s(LONG_MAX);
pinc(s);
U u(LONG_MAX);
pinc(u);
return 0;
}
可悲的是,它不與東西幫助像vector<A*>
:S
和U
沒有共同的祖先。如果我從另一個基類派生A
,我還必須將模板部分移到那裏,問題 - 哈! - 遞歸。
那麼,有什麼建議嗎?
編者注:已經吸取了教訓,我保存了原來的這個時候。 :)
我不知道我完全理解你的問題。你需要一個基類'A',它將有'++'運算符,但是它們的實現可以在派生類中被覆蓋。是這樣嗎? – Angew
@Angew我想要一種解決虛擬函數返回類型(表面上是人爲的)限制的方法。最初,虛擬函數根本不能返回不同的類型;然後放寬到協變類型。總比沒有好,但仍然不夠。後綴增量僅僅是這個特性變得特別不合邏輯的例子。 – sigil