C++静态工厂构造函数

Wil*_*lco 2 c++ constructor factory

我正在进行模拟,它需要创建多个相似的模型.我的想法是有一个名为Model的类,并使用静态工厂方法来构建模型.例如; Model :: createTriangleModel :: createFromFile.我从之前的Java代码中获取了这个想法,并且正在寻找在C++中实现它的方法.

这是我到目前为止提出的:

#include <iostream>

class Object {
    int id;

public:
    void print() { std::cout << id << std::endl; }

    static Object &createWithID(int id) {
        Object *obj = new Object();

        obj->id = id;

        return *obj; 
    }
};

int main() {
    Object obj = Object::createWithID(3);

    obj.print();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

关于这个的一些问题:

  • 这是一种被接受且干净的制作物品的方式吗?
  • 返回的引用是否始终确保正确删除对象?
  • 没有指针有没有办法做到这一点?

TC.*_*TC. 6

您的代码当前包含内存泄漏:new必须使用清除使用的任何对象delete.该createWithID方法最好不要使用new,看起来像这样:

static Object createWithID(int id) 
{
    Object obj;
    obj.id = id;
    return obj; 
}
Run Code Online (Sandbox Code Playgroud)

这似乎需要对象的附加副本,但实际上,返回值优化通常会使该副本被优化掉.

  • @ Cheersandhth.-Alf我认为Wilco试图做的是,构造函数的名称并不意味着**如何创建一个类,而不是**将创建什么**类.而不是多个构造函数或具有多个可选参数的构造函数,您可以使用具有有意义名称和更少可选参数或无意义bool参数的多个工厂方法.工厂方法有利有弊,但显然不是"荒谬"或"疯狂". (10认同)
  • 我不同意这一点,构造函数有一个限制:它们不能很好地扩展到大量的可选参数.此外,构造函数方法并不意味着正在创建什么,而名为**createFromFile**的函数会告诉您到底发生了什么. (3认同)

Ker*_* SB 6

只是为了记录,这里是这个程序在适当的C++中的样子:

class Object
{
    int id;

    // private constructor, not for general use
    explicit Object(int i) : id(i) { }

public:
    static Object createWithID(int id)
    {
        return Object(id);
    }
};

int main()
{
    Object obj1 = Object::createWithID(1);
    auto obj2 = Object::createWithID(2);   // DRY

    // return 0 is implied
}
Run Code Online (Sandbox Code Playgroud)

这可能不是人们通常所说的"工厂",因为工厂通常涉及一些动态类型选择.但是,有时使用术语"命名构造函数"来引用返回类实例的静态成员函数.


Che*_*Alf 5

这是一种被接受且干净的制作物体的方式吗?

它(不幸的是)被接受,但不干净。

只需使用构造函数即可代替工厂函数。

这就是他们的目的。

返回的引用是否始终确保正确删除对象?

该引用是无关紧要的,除非它会误导该功能的用户。

在您的示例中,引用显然误导了您自己,没有销毁动态分配的对象,而只是复制它。

最好返回一个智能指针。

但正如已经提到的,最好放弃工厂函数的想法。

它们在这里完全没有必要。

有没有办法在没有指针的情况下做到这一点?

不,如果“this”指的是动态分配,则不是,但是您可以而且应该使用构造函数而不是工厂函数。


例子:

#include <iostream>

namespace better {
    using std::ostream;

    class Object
    {
    public:
        auto id() const -> int { return id_; }
        explicit Object( int const id): id_( id ) {}
    private:
        int id_;
    };

    auto operator<<( ostream& stream, Object const& o )
        -> ostream&
    { return (stream << o.id()); }
}  // namespace better

auto main()
    -> int
{
    using namespace std;
    cout << better::Object( 3 ) << endl;
}
Run Code Online (Sandbox Code Playgroud)