繁体   English   中英

c ++中的auto_ptr问题

[英]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 MeyersEffective 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM