OMG. What is this nonsense?
It's not destroyed. It returns a new instance which can be used for whatever you want. In bithub's example, it is indeed destroyed directly, but that is the fault of the demonstrated code, not the design.
Ever heard of a factory? It usually uses a pattern like this, where the constructor is private.
bit∙hub [bit-huhb] n. A source and destination for information.
It was brewbuck's code...
It is too clear and so it is hard to see.
A dunce once searched for fire with a lighted lantern.
Had he known what fire was,
He could have cooked his rice much sooner.
You didn't take my code and add a main function, I didn't post that piece of crap class, you did. I ran the code to verify that it fails and immediately destroys the class, making it useless for anything but a collection of functions.
As the modifications I made show, it destroys the class immediately after the method exits. It does NOT return a new instance at all, there is no way of accessing the class because it is ........ing destroyed as soon as the method returns, so even if you added code to return this, it would point to an invalid location that will crash if you try to access the class since it was ........ing destroyed.Originally Posted by Elysia
The code works. I don't know what example you are using but try this:
A key here is that though the default constructor is private, the copy constructor is not.Code:#include <iostream> class NotInheritable { public: static NotInheritable Create() { return NotInheritable(); } void foo() { std::cout << "foo\n"; } private: NotInheritable() {} }; int main() { NotInheritable var = NotInheritable::Create(); var.foo(); }
And no, you can't add code to return this, because Create is a static method.
It is too clear and so it is hard to see.
A dunce once searched for fire with a lighted lantern.
Had he known what fire was,
He could have cooked his rice much sooner.
Which makes it useless as there is no way to access the class.And no, you can't add code to return this, because Create is a static method.
The code
at least works at producing usable classes, the code originally posted did not. Although I personally woudl never use this method as it seems to be much more work than simply using new. Particularly if you are creating the class in one thread and using it in another. This method would destroy the class when var1/var2 goes out of scope.Code:#include <iostream> class NotInheritable { public: static NotInheritable Create() { return NotInheritable(); } void foo() { std::cout << this << "\n"; } private: NotInheritable() {} }; int main(){ NotInheritable var1 = NotInheritable::Create(); var1.foo(); NotInheritable var2 = NotInheritable::Create(); var2.foo(); }
Last edited by abachler; 12-18-2009 at 06:22 PM.
My mistake, brewbuck posted it, you just quoted it.
That's where you're wrong. The class is copied. It is the equivalent to doing:
The object is copied before it is destroyed. That is why it is still valid for the caller.Code:std::string get_string() { return std::string("hello"); } void foo() { std::cout << "size is " << get_string().size() << std::endl; }
bit∙hub [bit-huhb] n. A source and destination for information.
They're right, Abachler. Consider:
The temporary isn't destroyed until the final print statement executes...Code:#include <iostream> #include <string> using namespace std; class example { public: example const& print( string const& text ) const { cout << reinterpret_cast< int const* >( this ) << " : " << text << endl; return *this; } static example create( void ) { return example( ); } example( example const& ) { print( "example( example const& )" ); } ~example( void ) { print( "~example( void )" ); } private: example( void ) { print( "example( void )" ); } }; int main( void ) { example::create( ).print( "1" ).print( "2" ).print( "3" ) .print( "4" ).print( "5" ).print( "6" ).print( "7" ) .print( "8" ).print( "9" ).print( "10" ); return 0; }
Only because the methods are recursively calling the class, once the call chain ends and the variable goes out of scope, the class is automatically destroyed, which may be fine for int main{ Foo() } examples, but it just will not do when creating the object and passing it to another thread, e.g. in a server application using separate listen() and processing threads.. While you can create a pointer to the object and pass that, you still have the scope issue, if the creating thread terminates, the object goes out of scope, causing the recipient thread to try to access an object that no longer exists. Using new, and creating it properly completely avoids this issue altogether. The object is never destroyed until your application explicitly delete's it.
It's poor design, regardless of whether or not it compiles and runs.
True, you couldn't pass a reference to the temporary to another thread, but the same holds for any non-global variable from an unrelated scope. No problem, you just need to pass a copy to the thread. All it really boils down to, then, is that the class has to be copy-constructible. Even so, the compiler can still choose to employ "return value optimization" (RVO), in which case the temporary is eliminated altogether. For example, when I compile and run this:
...The output is:Code:int main( void ) { example copy = example::create( ); copy.print( "1" ).print( "2" ).print( "3" ) .print( "4" ).print( "5" ).print( "6" ).print( "7" ) .print( "8" ).print( "9" ).print( "10" ); return 0; }
0x43f003 : example( void )
0x43f003 : 1
0x43f003 : 2
0x43f003 : 3
0x43f003 : 4
0x43f003 : 5
0x43f003 : 6
0x43f003 : 7
0x43f003 : 8
0x43f003 : 9
0x43f003 : 10
0x43f003 : ~example( void )
So, the code that was originally posted by Brewbuck was neither broken nor poor design - it's a perfectly sound solution to the problem, actually. Of course, personally, I'd never use it - I don't even bother with protected/private encapsulation in my own code, most of the time. The way I see it, if I don't want to have easy access to the internals, I can just mangle the member names - that way, if I really *do* need to mess with things, I can...the obfuscated identifier is reminder enough that I'm flirting with disaster!
Last edited by Sebastiani; 12-18-2009 at 09:22 PM. Reason: grammer incorrect was