Thread: c++ equivalent for C#'s "sealed override"?

  1. #46
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by bithub View Post
    It throws an error because you're doing it wrong...

    And there is no memory leak, and I'm not calling the member function without a class instance. The object is copy constructed when it is returned.

    You can just as easily modify the Create() function to return a pointer from the heap if you desire it that way (similar to the singleton design pattern).
    The class is instantly destroyed as soon as the create method returns. Returning this would be pointless. I'm not doing it wrong because I don't do it that way, it's your class, you did it wrong. All I did was add a few lines to return proof that it is fail.

  2. #47
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #48
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by abachler View Post
    The class is instantly destroyed as soon as the create method returns. Returning this would be pointless. I'm not doing it wrong because I don't do it that way, it's your class, you did it wrong. All I did was add a few lines to return proof that it is fail.
    How about you run the code before spouting off complete nonsense. Add prints to the constructor, copy constructor, and destructor, and learn what is actually going on. Also, it's not really my class. I took your code, and added a main() function. Remember?
    bit∙hub [bit-huhb] n. A source and destination for information.

  4. #49
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    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.

  5. #50
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by bithub View Post
    How about you run the code before spouting off complete nonsense. Add prints to the constructor, copy constructor, and destructor, and learn what is actually going on. Also, it's not really my class. I took your code, and added a main() function. Remember?
    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.

    Quote Originally Posted by Elysia
    It's not destroyed. It returns a new instance which can be used for whatever you want.
    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.

  6. #51
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    The code works. I don't know what example you are using but try this:
    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();
    }
    A key here is that though the default constructor is private, the copy constructor is not.

    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.

  7. #52
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    And no, you can't add code to return this, because Create is a static method.
    Which makes it useless as there is no way to access the class.

    The code
    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();
    	}
    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.
    Last edited by abachler; 12-18-2009 at 06:22 PM.

  8. #53
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by abachler View Post
    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.
    My mistake, brewbuck posted it, you just quoted it.


    Quote Originally Posted by abachler View Post
    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.
    That's where you're wrong. The class is copied. It is the equivalent to doing:

    Code:
    std::string get_string() { return std::string("hello"); }
    
    void foo() { 
        std::cout << "size is " << get_string().size() << std::endl;
    }
    The object is copied before it is destroyed. That is why it is still valid for the caller.
    bit∙hub [bit-huhb] n. A source and destination for information.

  9. #54
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    They're right, Abachler. Consider:

    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;	
    }
    The temporary isn't destroyed until the final print statement executes...

  10. #55
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by Sebastiani View Post
    The temporary isn't destroyed until the final print statement executes...
    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.

  11. #56
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    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:

    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;	
    }
    ...The output is:

    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

  12. #57
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by abachler View Post
    It's poor design, regardless of whether or not it compiles and runs.
    I've never heard of the factory pattern being a poor design before.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Equivalent of Dos 'copy' in C ?
    By YetBo in forum C Programming
    Replies: 17
    Last Post: 11-04-2009, 10:10 PM
  2. Pointer equivalent to array notation
    By bekkilyn in forum C Programming
    Replies: 4
    Last Post: 12-06-2006, 08:22 PM
  3. Replies: 10
    Last Post: 08-17-2005, 11:17 PM
  4. Header File Question(s)
    By AQWst in forum C++ Programming
    Replies: 10
    Last Post: 12-23-2004, 11:31 PM
  5. Replies: 0
    Last Post: 11-01-2002, 11:56 AM