Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过基类';仅将对象创建为共享指针;创建'-方法_C++_C++11_Constructor_Shared Ptr - Fatal编程技术网

C++ 通过基类';仅将对象创建为共享指针;创建'-方法

C++ 通过基类';仅将对象创建为共享指针;创建'-方法,c++,c++11,constructor,shared-ptr,C++,C++11,Constructor,Shared Ptr,我试图通过调用一个名为“create”的静态方法来实现应用程序中的某些对象只能被构造为共享的\u ptr 当然,我可以通过直接将静态“create”方法添加到所有相应的类中来实现这一点。然而,这意味着我必须在几乎所有的类中重复非常相似的代码。宏可以工作,但我觉得这不是很优雅 我想出了另一种方法,从实现“create”方法并返回指针的模板化“BaseObject”类派生所有类。除了std::make_shared在受保护时无法访问其子类的构造函数之外,这几乎是可行的 非解决方案是将子类构造函数公开

我试图通过调用一个名为“create”的静态方法来实现应用程序中的某些对象只能被构造为共享的\u ptr

当然,我可以通过直接将静态“create”方法添加到所有相应的类中来实现这一点。然而,这意味着我必须在几乎所有的类中重复非常相似的代码。宏可以工作,但我觉得这不是很优雅

我想出了另一种方法,从实现“create”方法并返回指针的模板化“BaseObject”类派生所有类。除了std::make_shared在受保护时无法访问其子类的构造函数之外,这几乎是可行的

非解决方案是将子类构造函数公开(请参见下面示例中的(1))。但是现在Foo可以正常地重新构造,这将破坏整个要点。另一种解决方案是在子类中建立BaseObject的好友关系,并直接使用shared_ptr(参见示例中的(2))

这两种解决方案都给子类的实现者带来了额外的负担。因为他们必须找到一种使构造函数非公共的替代方法,或者放置一个友元声明。(2)解决方案还有一个问题,即无法使用更高效的make_共享

我的问题是:有没有更好的方法

template<class T>
class BaseObject
{
public:
    typedef std::shared_ptr<T> SharedPtr;

    template<class... Args>
    static typename BaseObject<T>::SharedPtr create(Args&&... args)
    {
        return std::make_shared<T>(args...);
        //return std::shared_ptr<T>(new T(args...)); (2)
    }
};

class Foo : public BaseObject<Foo>
{
//friend BaseObject<Foo>; (2)

protected: //public (1)
    Foo(int a = 0) : m_foo(a) {}

private:
    int     m_foo;
};


int main(int argc, char* argv[])
{
    Foo::SharedPtr bla = Foo::create(1);
    return 0;
}
模板
类基类对象
{
公众:
typedef std::shared_ptr SharedPtr;
模板
静态typename BaseObject::SharedPtr创建(Args&&…Args)
{
返回std::使_共享(args…);
//返回std::shared_ptr(新的T(参数…);(2)
}
};
类Foo:publicbaseObject
{
//友元对象;(2)
受保护公众(1)
Foo(int a=0):m_Foo(a){}
私人:
林文福,;
};
int main(int argc,char*argv[])
{
Foo::SharedPtr bla=Foo::create(1);
返回0;
}
更新:

他们传递的关键习语似乎为我此刻提供了最好的解决方案:

template<class T>
class BaseObject
{
public:
    typedef std::shared_ptr<T> SharedPtr;

    class Key
    {
        friend class BaseObject<T>;
        Key() {}
    };

    template<class... Args>
    static typename BaseObject<T>::SharedPtr create(Args&&... args)
    {
        return std::make_shared<T>(Key(), args...);
    }
};

class Foo : public BaseObject<Foo>
{
public:
    Foo(BaseObject<Foo>::Key, int a = 0) : m_foo(a) {}

private:
    int     m_foo;
};
模板
类基类对象
{
公众:
typedef std::shared_ptr SharedPtr;
类密钥
{
友元类基本对象;
键(){}
};
模板
静态typename BaseObject::SharedPtr创建(Args&&…Args)
{
返回std::make_shared(Key(),args…);
}
};
类Foo:publicbaseObject
{
公众:
Foo(BaseObject::Key,int a=0):m_Foo(a){}
私人:
林文福,;
};
好处是:

  • 只能通过以下方式将Foo对象创建为共享\u ptr Foo::创建
  • 无需在Foo中添加复杂的好友声明
  • std::make_shared仍然有效

此解决方案的唯一问题是需要将“Key”作为构造函数中的第一个参数。但我可以接受

更好是主观的,但我相信如果您将构造函数设置为私有,并将
std::make_shared
设置为友元函数,会更直观一些。这样,唯一可以创建对象的函数就是
std::make_shared
,您可以编写

std::shared_ptr<Foo> ptr = std::make_shared<Foo>(12);
因此,任何未来的代码读者都可以理解您的意思,而无需实际查看
Foo

更新

我尝试过我写的东西,但没有真正起作用。下面是一个类似问题的答案,很可能也适用于您的问题:

更新2

下面是如何让它工作的(VC++2013)

#包括
使用名称空间std;
福班
{
受保护的:
Foo(int a=0):m_Foo(a){}
私人:
林文福,;
好友共享\u ptr make_shared();
朋友类(参考)(计数)对象;;
};
int main()
{
共享的\u ptr foo=使\u共享(12);
返回0;
}

\u Ref\u count\u obj
是由
使共享
内部使用的,这就是为什么您也需要与之成为朋友。

此外,您还应该从启用共享这一点派生。请参阅此处的详细信息:@Sarang是的,如果他愿意使用boost,但在他的示例中,它确实是一个STL共享指针。@GáborAngyal感谢您的回答。这个解决方案的主要问题是friend'ing std::make_shared将是非常特定于实现的。对VC++标准库的更新可能会破坏所有代码,并且需要在libc++和libstdc++上完全不同的代码。从用户和维护的角度来看,这对我来说是行不通的。但如果你声明make_shared为好友,那么你就允许everywhere创建对象实例作为共享指针。
Foo::SharedPtr bla = Foo::create(1);
#include <memory>

using namespace std;

class Foo
{
protected:
    Foo(int a = 0) : m_foo(a) {}

private:
    int     m_foo;

    friend  shared_ptr<Foo> make_shared<>();
    friend class _Ref_count_obj<Foo>;
};



int main()
{
  shared_ptr<Foo> foo = make_shared<Foo, int>(12);
  return 0;
}