我正在閱讀Scott Meyers的智能指針上的項目28 更有效的C++並存在以下問題。在隱式轉換的智能指針上刪除函數調用中的歧義
完整的演示可在http://ideone.com/aKq6C0找到。
派生類指針可以隱含地轉換爲基類指針:
class Base {};
class Derived : public Base {};
void foo(Base* b) { cout << "foo called on Base pointer" << endl;}
Derived *d = new Derived();
foo(d); //No problem
但這樣的隱式轉換不能發生用於智能指針,即SmartPtr<Derived>
不能隱式轉換爲SmartPtr<Base>
。所以,我們用一個成員模板這樣的轉換:
template<typename T>
class SmartPtr {
public:
//constructors, operator->, etc
//member template for type conversion
template<NewType>
operator SmartPtr<NewType>() {
return SmartPtr<NewType>(pointee);
}
private:
T* pointee;//the raw pointer
};
這幾乎可以工作,但它會引起歧義:
class Remote {};
class Base : public Remote {};
class Derived : public Base {};
void foo(const SmartPtr<Remote>& p) { cout << "remote" << endl;}
void foo(const SmartPtr<Base>& p) { cout << "base" << endl;}
SmartPtr<Derived> d(new Derived());
foo(d);//compile error: ambiguity
在這個例子中,編譯器不知道它是否應該d
轉換爲SmartPtr<Base>
或SmartPtr<Remote>
,儘管對於原始指針Base
顯然是優越的。這本書說
我們可以做的最好的辦法是使用成員模板生成轉換函數,然後在出現歧義結果的情況下使用強制轉換。
但是我們到底該如何施展? foo(static_cast<SmartPtr<Base>>(d))
也不能編譯。從錯誤消息中我可以看出,錯誤來自在SmartPtr
的複製構造函數中使用非const引用。我想知道什麼是進行函數調用的正確方法。
沒有回答qustion,但'返回的SmartPtr(足尖e);'看起來不正確,你需要像'std :: week_ptr'這樣的東西 –
你應該看看標準的智能指針,以及它們如何將轉換(例如)從'std :: shared_ptr'轉換爲'std :: shared_ptr '當(並且僅當)'Derived *'可以轉換爲'Base *'時。 –
您的演員表是正確的,缺少的是你的拷貝構造函數的代碼。如果你有一個需要非const的參考 - 你會得到你提到的錯誤,如果你只需要將ref修改爲在ct中的const並且代碼將被編譯(測試) –