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

  1. #31
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I'm no experienced Java dev, so I cannot comment on that.
    I did see some silly code that did restrict inheritance with the use of final, though. Of course, this was just some homework...
    Well, I'm still no fan of final, and I'd probably never use it, but whatever is, is, I suppose. No way to change that.
    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.

  2. #32
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by brewbuck View Post
    I think your explanation is relatively clear, but I am having a hard time imagining what sort of function would A) be virtual and B) be so simple that inlining it makes sense.
    It would be useful for any case where the base class is really an interface, and the derived implementation is a simple accessor or mutator.
    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.

  3. #33
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elysia View Post
    I'm no experienced Java dev, so I cannot comment on that.
    I did see some silly code that did restrict inheritance with the use of final, though. Of course, this was just some homework...
    Well, I'm still no fan of final, and I'd probably never use it, but whatever is, is, I suppose. No way to change that.
    You can restrict inheritance in C++ by declaring the constructors private, and providing a static "constructor" function:

    Code:
    class NotInheritable
    {
    public:
        static NotInheritable Create() { return NotInheritable(); }
    
    private:
        NotInheritable();
    };
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #34
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by bithub View Post
    It depends. It's easy to say "that's bad design" in theory. On the other hand, there may be some valid case where your derived class needs to call a virtual function from the constructor. Now you don't want any classes that are deriving from you to override that same virtual function due to the odd behavior that would produce. In this case, a "final" keyword would be nice to have.
    It's easy to say it's bad design because it is. C/C++ are not intended to be 'programmer safe'. They are intended to allow real programmers, as opposed to script kiddies, to use the code in the most flexible manner possible. Adding a keyword just to prevent some particularly bad design choice from crashing the system merely leads to portability problems. This isn't a lack of a feature in C++, its a lack of a feature in C# and that feature is called flexibility. However contrived an example you can present, I am pretty sure there exist more instances of code where 'final' is used as a variable name than exist real instances where final will prevent bad code.

    There has never been, nor will there ever be, a programming language in which it is the least bit difficult to write bad code.

    In fact I can foresee a case where it would CAUSE bad code. i.e. if I have a derived class that must implement new behavior for a finalized method, what will happen, will C# spit an error requiring me to remove the final keyword, thereby breaking all the other derived classes, or will it silently fail to implement my over-ridden method and lead to lost man hours tracking down a bad design choice?

    No, it is better that the final keyword not even exist in C++. That way the programmer must explicitly decide whether to override a method or not. This would of course all come out in the RFC discussions if C# wasn't an entirely contrived language that brings nothing to the table. MS just felt in its hubris that 'they know best' and is trying to force this piece of crap language on people.
    Last edited by abachler; 12-18-2009 at 03:55 PM.

  5. #35
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by King Mir View Post
    It would be useful for any case where the base class is really an interface, and the derived implementation is a simple accessor or mutator.
    That could be achieved with templates and concepts, but unfortunately we don't have formal concepts yet.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #36
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by brewbuck View Post
    You can restrict inheritance in C++ by declaring the constructors private, and providing a static "constructor" function:

    Code:
    class NotInheritable
    {
    public:
        static NotInheritable Create() { return NotInheritable(); }
    
    private:
        NotInheritable();
    };
    a constructor function must be public.

  7. #37
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    A constructor must be public? Since when?
    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.

  8. #38
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    @abachler
    Where bithub's example seems most likely to fix a problem as I see it is if derived1 and base are part of a librairy, and derived2 is written by someone using that librairy. The documentation of derived1 may fail to mention that foo is called by a constructor, or it change what it does in different versions. If is possible to document that derived1 is not meant to be derived from, but there may not be a problem with deriving from derived1 excepting this problem. So the best solution is to add a final like feature.

    As for adding keywords, CornedBee said that final would be an attribute, not a keyword so the problem does not exist as you describe. Attributes are surrounded by double brackets which do not occur in current C++.
    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.

  9. #39
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by King Mir View Post
    As for adding keywords, CornedBee said that final would be an attribute, not a keyword so the problem does not exist as you describe. Attributes are surrounded by double brackets which do not occur in current C++.
    In C++ it would have to be implemented as a keyword.

    And again, C++ is not intended to prevent a programmer from shooting themselves in the foot, it is intended to allow maximum flexibility. There is no point in restricting the use of derived methods if the programmer wishes to do so. If you need to restrict inheritance then simply make the method private or protected, or better yet Don't declare it virtual in the first place and it can no longer be inherited. You can do this in C# as well, so adding final was pointless. Declaring a method virtual and then finalizing it is basically just removing everything that virtual did in the first place. So what is next, keywords to let you declare a variable as type double, then a keyword to undeclare it so that you can redeclare it as int? I think final is a solution in search of a problem that doesn't exist, and for which if it did exist, there are already better solutions in place.
    Last edited by abachler; 12-18-2009 at 04:29 PM.

  10. #40
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by abachler View Post
    a constructor function must be public.
    It must?

    Code:
    #include <iostream>
    class NotInheritable
    {
    public:
        static NotInheritable Create() { return NotInheritable(); }
        void foo() { std::cout << "foo\n"; }
    
    private:
        NotInheritable() {}
    };
    
    int main()
    {
        NotInheritable::Create().foo();
    }
    bit∙hub [bit-huhb] n. A source and destination for information.

  11. #41
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by bithub View Post
    It must?

    Code:
    #include <iostream>
    class NotInheritable
    {
    public:
    static NotInheritable Create() { return NotInheritable(); }
        void foo() { std::cout << "foo\n"; }
    
    private:
        NotInheritable() {}
    };
    
    int main()
    {
        NotInheritable::Create().foo();
    }
    Code:
    NotInheritable* pTest = new NotInheritable();
    throws an error.
    Quote Originally Posted by Visual Studio
    .\main.cpp(13) : error C2248: 'NotInheritable::NotInheritable' : cannot access private member declared in class 'NotInheritable'
    1> .\main.cpp(9) : see declaration of 'NotInheritable::NotInheritable'
    1> .\main.cpp(3) : see declaration of 'NotInheritable'
    Create is not a constructor, it is an method function, there is a big difference. I also suspect that you are either directly calling the member function without creating an instance of the class, or you are leaking memory as there is no way to delete the instance without a pointer and no way to guarantee which instance of the class you are accessing. After testing, it appears that you are actually accessing a new instance each time, so there is no way to make the class more complex, e.g. with member variables, as they are destroyed after a single function call. So basically this kludge is nothing but a way to group a set of functions together, something that could more easily be done by simply using a separate namespace, since you are already creating a namespace to begin with.

    Code:
    #include <iostream>
    
    class NotInheritable {
    public:
    	static NotInheritable Create() { return NotInheritable(); }
    	void foo() { std::cout << "foo\n" << this << "\n" << this->Test << "\n"; this->Test++; }
    	int Test;
    
    private:
    	NotInheritable() { this->Test = 0; }
    	};
    
    int main(){
    	//NotInheritable* pTest = new NotInheritable();
    
    	NotInheritable::Create().foo();
    	NotInheritable::Create().foo();
    
    	return 0;
    	}
    Last edited by abachler; 12-18-2009 at 05:00 PM.

  12. #42
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by abachler View Post
    In C++ it would have to be implemented as a keyword.
    Not if it's as CornedBee describes. C++0x attributes are described in Wikipedia here. It doesn't mention final, but if its in C++0x it would use the same type of syntax.

    And again, C++ is not intended to prevent a programmer from shooting themselves in the foot, it is intended to allow maximum flexibility. There is no point in restricting the use of derived methods if the programmer wishes to do so. If you need to restrict inheritance then simply make the method private or protected and it can no longer be inherited. You can do this in C# as well, so adding final was pointless.
    Making a method protected or private has the side effect that it can no longer be called be a non derived pointer outside the class. That's not the intent of final/sealed.

    C++ is intended to make it hard for programmers to accidentally shoot themselves in the foot. A final key word like feature for methods would in fact add flexibility because where as before the danger of constructor calling a virtual method would be a worry for deriving from a class that is not intended to be derived from. With that worry removed, deriving from a class that not so risky.

    But this is secondary to the optimization benefits that final and sealed provide. High potential for optimization is a goal of C++.
    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.

  13. #43
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by abachler View Post
    Code:
    NotInheritable* pTest = new NotInheritable();
    throws an error
    The point is to force the user to use the static method Create to create an instance...
    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.

  14. #44
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by abachler View Post
    Code:
    NotInheritable* pTest = new NotInheritable();
    throws an error. Create is not a constructor, it is an initialization function, there is a big difference. I also suspect that you are either directly calling the member function without creating an instance of the class, or you are leaking memory as there is no way to delete the instance without a pointer and no way to guarantee which instance of the class you are accessing.
    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).
    bit∙hub [bit-huhb] n. A source and destination for information.

  15. #45
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Re: not declaring it as virtual in the first place.
    That's only possible if the method in question is of the base class. In the example, derived1 calls a function that is made virtual in the base class.

    Again, the two solutions are either to avoid calling the virtual function, or to declare the function as final. Sometimes the second would seem more elegant.
    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.

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