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

  1. #16
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Inline is a slippery slope that I avoid and this thread is proof why. There are millions of answers and possiblities as to what each compiler does and does not do for inline. B/c of this I avoid using it. It's almost harder to figure out when the compiler will or will not inline than it is to take the hit for the function call and make sure the function is optimized.

    AFAIK there is no equivalent to sealed in C++. I personally find it useless in C# b/c as abachler said if you do not want to override then don't. If you derive from the interface, however, you should be forced to implement all of it's pure virtual functions. I can't think of a reason in the world why you would need to prevent other programmers from implementing a base class pure virtual or virtual function. If a function is declared as pure virtual then you are essentially saying you must provide an implementation and if you declare it as virtual you are saying you can provide an alternate implementation. If you don't want anyone providing a different impl for the function then don't declare it in a manner that clearly is intended for that very purpose.
    Last edited by VirtualAce; 12-17-2009 at 06:01 PM.

  2. #17
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    There are some (albiet rare) cases where you have a derived class which overrides some functions, but you don't want any class to derive from your class and override some of these same functions. In this a final/sealed C++ keyword could be useful. For the most part, you can accomplish the same thing by adding a comment that says, "DO NOT OVERRIDE THIS FUNCTION"

    In C++ you can declare a base class function as non-virtual as a way of saying, "don't override this". In Java and C#, all functions are virtual, so declaring a function as final/sealed is the only way to accomplish the same thing. This is the main reason for the existence of these keywords -- it has nothing to do with function inlining.
    bit∙hub [bit-huhb] n. A source and destination for information.

  3. #18
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    it has nothing to do with function inlining.
    I don't think anyone was connecting the two. There are two topics running throughout this thread.

    There are some (albiet rare) cases where you have a derived class which overrides some functions, but you don't want any class to derive from your class and override some of these same functions. In this a final/sealed C++ keyword could be useful. For the most part, you can accomplish the same thing by adding a comment that says, "DO NOT OVERRIDE THIS FUNCTION"
    I would call that case a case of bad design since the same could be accomplished with a much better design.
    Last edited by VirtualAce; 12-17-2009 at 06:30 PM.

  4. #19
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by Bubba View Post
    I don't think anyone was connecting the two. There are two topics running throughout this thread.
    Post #7 connected the two.


    Quote Originally Posted by Bubba View Post
    I would call that case a case of bad design since the same could be accomplished with a much better design.
    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.
    bit∙hub [bit-huhb] n. A source and destination for information.

  5. #20
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by bithub View Post
    This is the main reason for the existence of these keywords -- it has nothing to do with function inlining.
    Yes it does. A virtual function cannot in the general case be inlined. I don't know C# but in java, all references are potencially references to a derived class, and therefore every call to a non final function requires vtable lookup. This prevents inlining. By declaring a method final vtable look up is not neccessairy. the function is effectively non virtual when called with a reference to the class in which that function is declared final. This allows inlining.

    This is the only real use of the final functions. In other cases using final just unduly limits the programmer. If you are designing a module/package, and the function in question is to be derived within the module, then the final keyword is not useful, because it is plain to see that your more derived classes do not derive the base class. If you are instead designing a class that is meant to be derived from across API boundaries, then you are unduly limiting the user of your class. What benefit does the user receive of being unable to make a debug wrapper around calls to that function?

    Only functions that you think are candidates for inlining should be declared final in Java.

    You may have a point with calls from a constructor. I'm not totally convinced though. Can you maybe give a code example?
    Last edited by King Mir; 12-18-2009 at 03:31 PM.
    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.

  6. #21
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by King Mir View Post
    @bithub
    You may have a point with calls from a constructor. I'm not totally convinced though. Can you maybe give a code example?
    This is a very contrived example (not compiled, so please excuse any typos):
    Code:
    #include <iostream>
    class base
    {
    public:
        virtual void foo(void) {
            std::cout << "in base foo()\n";
        }
    };
    
    class derived1 : public base
    {
    public:
        derived1(void) {
            foo();
        }
    
        // would be nice to declare this as "final"
        void foo(void) {
            std::cout << "in derived1 foo()\n";
        }
    };
    
    class derived2 : public derived1
    {
    public:
        void foo(void) {
            std::cout << "in derived2 foo()\n";
        }
    };
    
    int main()
    {
        base* b = new derived2();
        b->foo();
        delete b;
    }
    Depending on the work being done in foo(), this can have some unintended consequences since creating a new derived2 object will call derived1's foo() even though derived2 has overridden the function.
    bit∙hub [bit-huhb] n. A source and destination for information.

  7. #22
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    As a safety rule, you simply should never call virtual functions, or functions that transitively call virtual functions, from the constructor. I can't imagine a design where doing so would be the right thing.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #23
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by CornedBee View Post
    As a safety rule, you simply should never call virtual functions, or functions that transitively call virtual functions, from the constructor. I can't imagine a design where doing so would be the right thing.
    Of course. But if c++ had the equivalent of the "final" keyword, this "safety rule" would not be needed.
    bit∙hub [bit-huhb] n. A source and destination for information.

  9. #24
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I don't like it. It hinders design, like some standard library classes which insists on using private instead of protected.
    And it will probably be abused too. It's a shame that we are getting a final keyword in C++.

    As for the whole inlining topic... what's the deal with avoiding it? Let the compiler do its job. Whether it inlines them or not is up to the compiler and not to us. Why should we care? If it does it, then great. If not, no big loss. Let's just not depend on the compiler inlining it for us.
    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.

  10. #25
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    @bithub
    I suppose there are cases where that could cause problems.
    Last edited by King Mir; 12-18-2009 at 03:27 PM.
    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.

  11. #26
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Would that not imply a broken optimization? Sure, those things happen, but we don't turn off optimizations because they "might" break something, do we?
    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.

  12. #27
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    @Elysia
    The issue is that it is hard for the compiler to inline virtual functions, because whenever a method is accessed though a class pointer or reference it has to do vtable lookup. Only if the compiler somehow knows that a reference or pointer is not to a child of the object type pointed to can vtable lookup be inlined. A final-like property would eliminate this problem, and inlineing is made possible as a result. This is how the final key word is useful in Java. Even without inlining, it would be eliminating a level of indirection (in C++), but inining is the real gain.

    I seem to be repeating this for the third time now. Maybe I should let somebody else explain it.
    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. #28
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I saw that, but I don't like it. It limits design options and can be easily abused.
    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. #29
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by King Mir View Post
    I seem to be repeating this for the third time now. Maybe I should let somebody else explain it.
    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.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  15. #30
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    There's a lot in C++ that can be abused. C++ is meant to be a powerful and fast, and this aids in that goal. Being hard to abuse is not a design goal of C++.

    Final is not used much for functions in Java. Why would it become a problem in 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.

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