Suppose you have a cl开发者_JAVA技巧ass with a member variable declared constant.
class Test
{
public:
Test(const int const_param) : const_member_(const_param) {}
private:
const int const_member_;
};
We want a function that will return an instance of this object either as a "return value"
Test Foo();
Test* Foo();
Test& Foo();
or as an "output parameter" (i.e. a pointer that is passed in).
void Foo(Test* test);
void Foo(Test** test); // maybe this is more correct?
Note this function is the only thing that can create the object (in the above example, Foo
will be the only thing that knows the value of const_param
and can thus create a Test
object)
What would be the best way to do something like this? Is this even possible?
You can just return such an object by copy, unless you have good reason do avoid this design:
Foo make_foo()
{
int n = get_mystery_value()
Foo x(n);
x.manipulate();
return x;
}
If you'd rather handle the object by pointer, use std::shared_ptr<Foo>
instead:
std::shared_ptr<Foo> make_foo()
{
int n = roll_dice();
auto px = std::make_shared<Foo>(n);
px->crazy_stuff();
return px;
};
Or, if you just need one handler object, use std::unique_ptr<Foo>
.
A bit of explanation: Having a constant member in your object essentially means that the object itself has the semantics of a constant object. It is OK to copy constants, but not to reassign them, so in your typical use case you would only create an object of this class once and not reassign it. A copy constructor is automatically defined for you, so you can go straight ahead and say:
int main()
{
Foo x = make_foo();
Foo y(make_foo()); // same thing
x.twiddle();
y.skedaddle();
// ...
}
Clearly you cannot and would not say x = make_foo();
, because your x
is semantically a constant thing for which reassignment doesn't make sense.
I just tried the following, and it works fine.
Test* Foo()
{
Test* x = new Test(5);
return x;
}
I don't think you need anything fancy.
A factory function (a function with exclusive rights to create objects of a particular type) should use that type as its return, not "return by argument."
If you must return by argument, C++ has no facility for putting the returned object on the stack as a temporary. Thus, the new object must be on the heap. Since in this case the pointer to the object, not its contents, are what you want to return, the function argument should be a modifiable pointer.
Raw pointers are usually bad news because you must remember to manually delete
appropriately. Smart pointer classes such as unique_ptr
and shared_ptr
are better practice, and auto_ptr
is more compatible but trickier to use.
void Foo(unique_ptr< Test > &test) {
test = new Test;
}
精彩评论