C++ c+中的自动ptr问题+;

C++ c+中的自动ptr问题+;,c++,C++,我是新来的。 我也是C++上的新手 这是我写的类和函数,但我得到了编译器错误 我的班级: class fooPlayer { public: void fooPlayerfunc(){}//doing something here char askYesNo(std::string question); }; class fooPlayerFactory { public: virtual std::auto_ptr<fooPlayer> Make

我是新来的。 我也是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;

};
我得到了一个错误: 错误C2558:类“std::auto_ptr”:没有可用的复制构造函数或复制构造函数声明为“显式”

我不知道如何更改它,即使在阅读了您代码中链接:

上的文档后:

auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
       my_player->fooPlayerfunc();
       return my_player;
}
auto_ptr fooPlayerFactory::MakePlayer(字符字母)常量
{
my_player->fooPlayerfunc();
返回我的_播放器;
}

这是一个常量函数,但
fooPlayerfunc
不是常量-我的编译器报告此错误,而不是您所说的错误。你发布的是真正的代码吗?

编辑:为了回应评论(这是正确的,我的错),我只留下了建议部分


最佳实践是让工厂方法只返回一个指向底层对象的普通旧指针,并让调用方决定如何管理所有权(auto_ptr、scoped_ptr或其他任何东西)。

我认为您实际上不想在这里构建动态对象。
工厂对象创建并返回一个对象,它通常不会在创建后保留对它的引用(除非您共享它),而且我实际上看不到您在任何地方创建播放器


如果您在(fooPlayerFactory)中仅在内部创建一个播放器。然后创建一个对象并返回对它的引用。

我看不到任何你构建的
my_player
,所以我感觉有些代码丢失了。具体来说,我认为您的构造函数有以下几行:

my_player = new fooPlayer()
fooPlayer
对象与
auto_ptr
对象不是一回事,而
auto_ptr
的设计是为了防止从一个对象分配到另一个对象,因为坦率地说,另一个更糟糕。有关详细信息,请查找(1)转换构造函数,(2)显式关键字,以及(3)复制构造函数和破坏性复制语义

您应该将构造函数更改为:

class fooPlayerFactory {
    public:
    fooPlayerFactory()
    {
        my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
    }
我将
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();
   }
};

出现错误的原因是,您正在调用fooPlayerFactory::MakePlayerO()中auto_ptr my_player的复制构造函数,这是一个const方法。这意味着它不能修改其成员

但是,auto_ptr的复制构造函数确实修改了右侧,因此返回my_player时会尝试将其指针更改为0(NULL),同时在返回值中将原始指针指定给auto_ptr

副本构建者的签名为

auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
auto_ptr::auto_ptr(auto_ptr&rhs)
不是

auto_ptr::auto_ptr(const auto_ptr&rhs)
auto_ptr的copy构造函数将指针的所有权分配给左手侧,然后右手侧什么也不保留

我认为您不想在这里使用auto\u ptr,您可能需要boost::smart\u ptr

看起来您混淆了auto_ptr的两种用途

第一种是作为穷人的助力::作用域的ptr。这是为了管理类中指针的单个实例,该类管理指针的生命周期。在这种情况下,您通常不会在类之外返回此指针(可以这样做,因为这是合法的,但是boost::smart\u ptr/boost::weak\u ptr会更好,这样客户端就可以参与指针的生命周期)

第二个是它的主要用途,即以异常安全的方式返回新创建的指向函数调用方的指针

乙二醇

auto_ptr foo(){
返回新的T;
}
空条(){
auto_ptr t=foo();
}

正如我所说,我认为你已经混合了这两种用法。auto_ptr是一种微妙的野兽,你应该仔细阅读auto_ptr文档。它在中也有很好的介绍。

而且您的代码有缺陷,任何实现虚拟方法的类都应该有一个虚拟析构函数。

绝对不同意。你不应该到处传递原始指针,因为它们很有可能被丢弃。如果您不确定是否返回std::auto_ptr。共享的\u ptr有一个构造函数,该构造函数接受自动\u ptr并从返回的自动ptr获取所有权_prt@martin-就我个人而言,我不同意你的观点-我宁愿由工厂的用户决定动态内存管理的策略。在这一点上,我支持Martin。您必须使用auto_ptr或类似工具来保护异常安全。然而,在上面的例子中使用auto_ptr看起来是假的。这正是我要说的。他没有说他得到错误的确切位置,但我希望它出现在调用复制构造函数的每个函数的return语句上。但是你的回答让我明白了+1
class fooPlayerFactory {
    public:
    fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new 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());
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();
   }
};
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
auto_ptr<T> foo() {
    return new T;
}

void bar() {
    auto_ptr<T> t = foo();
}