c++静态工厂构造函数
C++ static factory constructor
我正在制作模拟过程中,它需要创建多个相当相似的模型。我的想法是有一个名为Model的类,并使用静态工厂方法来构造模型。例如;Model::createTriangle或Model::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;
}
关于这个的一些问题:
- 这是一种被接受的、干净的制作对象的方式吗?
- 返回的引用是否总是确保正确地删除对象?
- 有没有办法做到这一点没有指针?
只是为了记录,下面是这个程序在适当的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
}
这可能不是人们通常所说的"工厂",因为工厂通常涉及一些动态类型选择。但是,有时使用术语"命名构造函数"来指返回类实例的静态成员函数。
您的代码当前包含内存泄漏:使用new
创建的任何对象都必须使用delete
清理。createWithID
方法最好不使用new
,看起来像这样:
static Object createWithID(int id)
{
Object obj;
obj.id = id;
return obj;
}
这似乎需要对象的额外副本,但实际上,返回值优化通常会导致该副本被优化掉。
这是一种被接受的、干净的制造物体的方式吗?
(不幸的是)它被接受了,但它不干净。
用构造函数代替工厂函数。
这就是它们的作用。
返回的引用是否总是确保正确地删除对象?
引用是不相关的,除非它误导了函数的用户。
在你的例子中,引用显然误导了你自己没有销毁动态分配的对象,而只是复制它。
最好返回一个智能指针。
但是正如已经提到的,最好放弃工厂函数的想法。
它们在这里完全没有必要。
有没有办法做到这一点没有指针?
不,如果"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;
}
通过调用Object *obj = new Object();
,您确实在堆上分配内存。在该语句之后的行中,确实返回了对该对象的引用。到目前为止,一切顺利,但是您永远不会删除创建的对象来实际释放内存。通过多次调用该函数,您将在内存泄漏中运行。
有两种可能的解决方法:
-
在堆栈上分配它就足够了static Object createWithID(int id);
将返回您创建的对象的副本,因此使用Object tmp; tmp.id = id;
-
使用c++11智能指针让它们处理内存。
#include <memory> static std::unique_ptr<Object> createWithID(int id) { std::unique_ptr<Object> tmp(new Object()); tmp->id = id; return std::move(tmp); }
这绝对是一种糟糕的创建对象的方式。每次调用createWithID
的时候,一个新的Object
就会在自由存储区被构造,并且永远不能被销毁。
你应该重写createWithID
为:
static Object createWithID(int id) {
Object obj;
obj.id = id;
return obj;
}
或者,您可以为您的Object
对象提供一个构造函数。
如果你想启用多态对象,你应该使用类似wheels::value_ptr的东西
除非您使用多态性,否则您的工厂函数没有理由返回任何类型的指针,它们可以按值返回对象。任何现代编译器都会做返回值优化,所以没有复制。
如果你是在一个"被接受和干净"的方式之后,那么这听起来相当基于意见,取决于这个类将如何使用,但我要做的是保持Model
的定义尽可能小。只包含正常使用所需的最少数量的构造函数来完成它的工作:
namespace Simulation {
class Model {
private:
int id_;
public:
explicit Model(int id) : id_(id) {}
// minimum required to do the job...
};
}
然后,我将分别定义创建各种风格的Model
的函数。例如,作为命名空间中的非成员、非友元函数:
namespace Simulation {
Model createTriangle(int id) {
Model model(id);
// do whatever you need to do to make it a triangle...
return model;
}
Model createSquare(int id) {
Model model(id);
// do whatever you need to do to make it a square...
return model;
}
}
这样,如果您发现需要另一种风格的Model
,则无需更改Model
类。如果需要,您的create函数甚至可以分布在多个文件中,或者成为Builder或Factory类的一部分。用法如下:
int main() {
Simulation::Model m1(0);
Simulation::Model m2 = Simulation::createTriangle(1);
Simulation::Model m3 = Simulation::createSquare(2);
}
- 在 C++ 中返回新的构造函数(*this)工厂
- 没有用于初始化模拟工厂的匹配构造函数
- 设计模式的工厂替代方法:具有不同构造函数的类
- 具有多个构造函数的C 通用工厂
- 将 C 结构工厂函数与其相应的 C++ 包装类构造函数合并
- 如何将一个类的构造函数的调用限制为仅其工厂类
- C 非堆工厂对象创建具有受保护的构造函数和复制构造函数
- 具有构造函数的可变参数模板参数的工厂类
- 我可以为带有参数的构造函数创建类工厂
- 使用工厂时如何"hide"构造函数?
- 在具有boost工厂的构造函数中传递参数
- boost::p ython 纯虚拟基类,具有静态工厂构造函数和 std::unique_ptr
- 虚拟构造函数习语与工厂设计
- c++11模板工厂模式和带参数的构造函数
- 如何将参数传递给工厂元素构造函数
- 将构造函数参数传递给模板函数工厂
- 具有异构构造函数约束的c++工厂模式
- 带有参数化构造函数的抽象工厂
- 如何在工厂函数中解析构造函数签名
- 有没有一个C++习语来形容这个丑陋的构造函数/工厂