[英]auto_ptr question in c++
我剛來這地方。 我也是C ++的新手所以這里是我寫的類和函數。但是我得到了編譯錯誤我的類:
class fooPlayer
{
public:
void fooPlayerfunc(){}//doing something here
char askYesNo(std::string question);
};
class fooPlayerFactory
{
public:
virtual std::auto_ptr<fooPlayer> MakePlayerX() const;
virtual std::auto_ptr<fooPlayer> MakePlayerO() const;
private:
std::auto_ptr<fooPlayer> MakePlayer(char letter) const;
std::auto_ptr<fooPlayer> my_player;
};
實施我的課程:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerX() const
{
char go_first = my_player->askYesNo("Do you require the first move?");
MakePlayer(go_first);
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerO() const
{
return my_player;
}
我的main()函數在這里:
int main()
{
fooPlayerFactory factory;
factory.MakePlayerX();
factory.MakePlayerO();
}
我收到錯誤:錯誤C2558:類'std :: auto_ptr <_Ty>':沒有可用的復制構造函數或復制構造函數被聲明為'explicit'
即使在閱讀此鏈接上的文檔后,我也不知道如何更改它:
出錯的原因是你在fooPlayerFactory :: MakePlayerO()中調用auto_ptr my_player的復制構造函數,這是一個const方法。 這意味着無法修改其成員。
但是,auto_ptr的復制構造函數會修改右側,因此返回my_player trys將其指針更改為0(NULL),同時將原始指針指定給返回值中的auto_ptr。
復制構造函數的簽名是
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
不
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
auto_ptr的復制構造函數將指針的所有權分配給左側,右側則不保留任何內容。
我不認為你想在這里使用auto_ptr,你可能想要boost :: smart_ptr
看起來你混淆了auto_ptr的兩個用途
第一個是窮人的boost :: scoped_ptr。 這是為了管理類中指針的單個實例,該類管理指針的生命周期。 在這種情況下,你通常不會在你的類之外返回這個指針(你可以這是合法的,但boost :: smart_ptr / boost :: weak_ptr會更好,所以客戶可以參與指針的生命周期)
第二個是它的主要目的是以異常安全的方式將新創建的指針返回給函數的調用者。
例如
auto_ptr<T> foo() {
return new T;
}
void bar() {
auto_ptr<T> t = foo();
}
正如我所說,我認為你混合了這兩個用法auto_ptr是一個微妙的野獸,你應該仔細閱讀auto_ptr文檔。 Scott Meyers在Effective STL中也很好地介紹了它。
在你的代碼中:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
這是一個const函數,但fooPlayerfunc
不是const - 我的編譯器報告此錯誤而不是你說的那個錯誤。 你發布真實的代碼嗎?
我不認為你真的想在這里構建動態對象。
工廠對象創建並返回一個對象,它通常在創建后不會保留對它的引用(除非你正在共享它),而我實際上並沒有看到你在創建播放器的任何地方。
如果你只在你的(fooPlayerFactory)內部創建一個玩家。 然后創建一個對象並返回對它的引用。
編輯:響應評論(這是正確的,我的壞),我只留下了建議部分。
最佳做法是讓工廠方法只返回一個指向底層對象的普通舊指針,讓調用者決定如何管理所有權(auto_ptr,scoped_ptr或其他)。
我沒有看到你構建my_player
任何地方,所以我感覺有些代碼丟失了。 具體來說,我認為你的構造函數有這一行:
my_player = new fooPlayer()
fooPlayer
對象與auto_ptr<fooPlayer>
對象auto_ptr<fooPlayer>
,而auto_ptr
是故意設計的,以防止從一個對象分配到另一個,因為坦率地說,替代方案更糟糕。 有關詳細信息,請查找(1)轉換構造函數,(2) explicit
關鍵字,以及(3)復制構造函數和破壞性復制語義。
您應該將構造函數更改為:
class fooPlayerFactory {
public:
fooPlayerFactory()
{
my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
}
或(使用成員初始化列表):
class fooPlayerFactory {
public:
fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new fooPlayer()) { }
解決方案並不漂亮,但正如我所說,由於一些非常神秘的細節,替代方案更糟糕。
不過,作為一點建議,你的生活比現在更難; 事實上可能會導致奇怪的錯誤。 auto_ptr
存在是為了管理對象的生命周期,但是你需要擔心my_player
的生命周期的唯一原因是你已經用new
分配了它。 但是沒有必要調用new
,事實上沒有必要保留my_player
。 除非fooPlayerFactory
是其他工廠的基類,否則不需要將函數標記為virtual
。
最初我認為你可以簡單地返回my_player
對象的副本,但是有一個問題:在從MakePlayer()
返回my_player
之前,你調用了一個方法,我認為該方法改變了my_player
的內部狀態。 進一步調用MakePlayer()
會再次改變狀態,我認為你最終my_player
處於錯誤的狀態。 相反,每個請求返回一個不同的fooPlayer
對象。 不要做內存管理,只是承諾構造對象。 這樣用戶可以決定內存分配:
fooPlayerFaclotry factory;
fooPlayer on_stack = factory.MakePlayerX();
fooPlayer* on_heap_raw_pointer = new fooPlayer(factory.MakePlayerO());
std::auto_ptr<fooPlayer> on_heap_managed_scope
= std::auto_ptr<fooPlayer>(factory.MakePlayerX());
我會改變fooPlayerFactory
看起來像這樣:
class fooPlayerFactory
{
private:
fooPlayer MakePlayer(const char letter) const
{
fooPlayer result;
result.fooPlayerfunc();
return result;
}
public:
fooPlayer* MakePlayerX() const
{
char go_first = askYesNo("Do you require the first move?");
return MakePlayer(go_first);
}
fooPlayer MakePlayerO() const
{
return fooPlayer();
}
};
您的代碼也是錯誤的,任何實現虛方法的類都應該有一個虛擬析構函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.