VC++ 2005: private virtual functions

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Nemanja Trifunovic

    #1

    VC++ 2005: private virtual functions

    Something I don't get it:

    Say we have:

    ref class Base {
    virtual void SomeVirtualFunc tion()
    {Console::Write Line(L"Base");}
    public:
    void SomeAccessibleF unction()
    {SomeVirtualFun ction();}
    };

    ref class Derived : public Base {
    virtual void SomeVirtualFunc tion()
    {Console::Write Line(L"Derived" );}
    };

    int main(array<Syst em::String ^> ^args)
    {
    Base^ handle = gcnew Derived();
    handle->SomeAccessible Function();

    return 0;
    }

    I would expect to get "Derived" as the result, right? However, I get
    "Base", and strange warnings during compilation:

    ".\PrivateVirtu al.cpp(8) : warning C4486: 'Base::SomeVirt ualFunction' :
    a private virtual method of a ref class or value class should be marked
    'sealed'
    ..\PrivateVirtu al.cpp(16) : warning C4486:
    'Derived::SomeV irtualFunction' : a private virtual method of a ref
    class or value class should be marked 'sealed'
    "

    If I try explicit overriding:

    ..\PrivateVirtu al.cpp(17) : error C3671: 'Derived::SomeV irtualFunction'
    : function does not override 'Base::SomeVirt ualFunction'
    ..\PrivateVirtu al.cpp(16) : warning C4486:
    'Derived::SomeV irtualFunction' : a private virtual method of a ref
    class or value class should be marked 'sealed'

    What is going on here?

  • Jochen Kalmbach [MVP]

    #2
    Re: VC++ 2005: private virtual functions

    Hi Nemanja![color=blue]
    > ref class Base {
    > virtual void SomeVirtualFunc tion()
    > {Console::Write Line(L"Base");}
    > public:
    > void SomeAccessibleF unction()
    > {SomeVirtualFun ction();}
    > };
    >
    > ref class Derived : public Base {
    > virtual void SomeVirtualFunc tion()
    > {Console::Write Line(L"Derived" );}
    > };
    >
    > int main(array<Syst em::String ^> ^args)
    > {
    > Base^ handle = gcnew Derived();
    > handle->SomeAccessible Function();
    >
    > return 0;
    > }
    >
    > I would expect to get "Derived" as the result, right? However, I get
    > "Base", and strange warnings during compilation:
    >
    > ".\PrivateVirtu al.cpp(8) : warning C4486: 'Base::SomeVirt ualFunction' :
    > a private virtual method of a ref class or value class should be marked
    > 'sealed'[/color]

    "private" virtual functions are useless! because nobody can overwrite it!

    You need to declare your virtual functions at least as "protected" !

    --
    Greetings
    Jochen

    My blog about Win32 and .NET

    Comment

    • Nemanja Trifunovic

      #3
      Re: VC++ 2005: private virtual functions

      > private" virtual functions are useless! because nobody can overwrite it!

      Read this article: http://www.gotw.ca/publications/mill18.htm

      Comment

      • Bo Persson

        #4
        Re: VC++ 2005: private virtual functions


        "Jochen Kalmbach [MVP]" <nospam-Jochen.Kalmbach @holzma.de> skrev i
        meddelandet news:ef7ldi2dFH A.3836@tk2msftn gp13.phx.gbl...[color=blue]
        > Hi Nemanja![color=green]
        >> ref class Base {
        >> virtual void SomeVirtualFunc tion()
        >> {Console::Write Line(L"Base");}
        >> public:
        >> void SomeAccessibleF unction()
        >> {SomeVirtualFun ction();}
        >> };
        >>
        >> ref class Derived : public Base {
        >> virtual void SomeVirtualFunc tion()
        >> {Console::Write Line(L"Derived" );}
        >> };
        >>
        >> int main(array<Syst em::String ^> ^args)
        >> {
        >> Base^ handle = gcnew Derived();
        >> handle->SomeAccessible Function();
        >>
        >> return 0;
        >> }
        >>
        >> I would expect to get "Derived" as the result, right? However, I get
        >> "Base", and strange warnings during compilation:
        >>
        >> ".\PrivateVirtu al.cpp(8) : warning C4486: 'Base::SomeVirt ualFunction'
        >> :
        >> a private virtual method of a ref class or value class should be
        >> marked
        >> 'sealed'[/color]
        >
        > "private" virtual functions are useless! because nobody can overwrite
        > it!
        >
        > You need to declare your virtual functions at least as "protected" ![/color]

        But note that this is so for managed code only. In real C++ it would
        have worked!


        Bo Persson


        Comment

        • Nemanja Trifunovic

          #5
          Re: VC++ 2005: private virtual functions

          Even in "old" Managed C++ it works.

          Comment

          • Tamas Demjen

            #6
            Re: VC++ 2005: private virtual functions

            It seems to be stupid from the C++ programmer's point of view, but then
            ..NET was not designed by C++ programmers.

            Unfortunately in .NET virtual functions can't be private, they must be
            protected. But even that modification won't solve your problem, you even
            have to declare the function override to override a virtual function.
            The correct code is

            ref class Base {
            protected:
            virtual void SomeVirtualFunc tion()
            {Console::Write Line(L"Base");}
            public:
            void SomeAccessibleF unction()
            {SomeVirtualFun ction();}
            };

            ref class Derived : public Base {
            protected:
            virtual void SomeVirtualFunc tion()
            {Console::Write Line(L"Derived" );}
            };

            I share your pain...

            Tom

            Nemanja Trifunovic wrote:[color=blue]
            > Something I don't get it:
            >
            > Say we have:
            >
            > ref class Base {
            > virtual void SomeVirtualFunc tion()
            > {Console::Write Line(L"Base");}
            > public:
            > void SomeAccessibleF unction()
            > {SomeVirtualFun ction();}
            > };
            >
            > ref class Derived : public Base {
            > virtual void SomeVirtualFunc tion()
            > {Console::Write Line(L"Derived" );}
            > };
            >
            > int main(array<Syst em::String ^> ^args)
            > {
            > Base^ handle = gcnew Derived();
            > handle->SomeAccessible Function();
            >
            > return 0;
            > }
            >
            > I would expect to get "Derived" as the result, right? However, I get
            > "Base", and strange warnings during compilation:
            >
            > ".\PrivateVirtu al.cpp(8) : warning C4486: 'Base::SomeVirt ualFunction' :
            > a private virtual method of a ref class or value class should be marked
            > 'sealed'
            > .\PrivateVirtua l.cpp(16) : warning C4486:
            > 'Derived::SomeV irtualFunction' : a private virtual method of a ref
            > class or value class should be marked 'sealed'
            > "
            >
            > If I try explicit overriding:
            >
            > .\PrivateVirtua l.cpp(17) : error C3671: 'Derived::SomeV irtualFunction'
            > : function does not override 'Base::SomeVirt ualFunction'
            > .\PrivateVirtua l.cpp(16) : warning C4486:
            > 'Derived::SomeV irtualFunction' : a private virtual method of a ref
            > class or value class should be marked 'sealed'
            >
            > What is going on here?
            >[/color]

            Comment

            • Tamas Demjen

              #7
              Re: VC++ 2005: private virtual functions

              Tamas Demjen wrote:[color=blue]
              > ref class Derived : public Base {
              > protected:
              > virtual void SomeVirtualFunc tion()
              > {Console::Write Line(L"Derived" );}
              > };[/color]

              Sorry I copied the wrong code:

              ref class Derived : public Base {
              protected:
              virtual void SomeVirtualFunc tion() override
              {Console::Write Line(L"Derived" );}
              };

              Note the override keyword, it indicates that the function is not
              replacing Base::SomeVirtu alFunction, but is overriding it.

              Tom

              Comment

              • Nemanja Trifunovic

                #8
                Re: VC++ 2005: private virtual functions

                Hi Tom.
                [color=blue]
                >Unfortunatel y in .NET virtual functions can't be private, they must be protected[/color]

                But I am pretty sure CLR allows private virtual functions. It works
                fine with old MC++.
                [color=blue]
                >But even that modification won't solve your problem, you even have to declare the function override to override a virtual function.[/color]

                Yep, just noticed this in the C++/CLI spec. Actually, I pretty much
                like this "controlled virtuality". Just have no idea why to disable
                private virtual functions. Any clues?

                Comment

                • Tamas Demjen

                  #9
                  Re: VC++ 2005: private virtual functions

                  Nemanja Trifunovic wrote:
                  [color=blue]
                  > Yep, just noticed this in the C++/CLI spec. Actually, I pretty much
                  > like this "controlled virtuality". Just have no idea why to disable
                  > private virtual functions. Any clues?[/color]

                  The reason I don't like this override keyword is that because if you
                  miss it, the function won't work like a virtual function anymore, and
                  there's not even a compiler warning. No override keyword == non-virtual
                  function, even if the virtual keyword is there. It's very frustrating
                  when you have a virtual function and it's not polymorphic.

                  If I make the virtual function private, I get the following .NET runtime
                  exception:

                  <quote>
                  An unhandled exception of type 'System.TypeLoa dException' occurred in
                  Virtual.exe

                  Additional information: Method 'SomeVirtualFun ction' on type 'Derived'
                  from assembly 'Virtual, Version=1.0.199 9.26811, Culture=neutral ,
                  PublicKeyToken= null' is overriding a method that is not visible from
                  that assembly.
                  </quote>

                  This is not a language feature, it's a .NET runtime exception, which
                  clearly states that overriding a private virtual function is not
                  supported by the runtime library.

                  I don't know if it's intentional, but this is happening with VC++ 2005
                  Beta2.

                  Tom

                  Comment

                  • Nemanja Trifunovic

                    #10
                    Re: VC++ 2005: private virtual functions

                    You are right - it does throw. However, with VC++ 2003, the following
                    code works just fine:

                    __gc class Base {
                    virtual void SomeVirtualFunc tion()
                    {Console::Write Line(S"Base");}
                    public:
                    void SomeAccessibleF unction()
                    {SomeVirtualFun ction();}
                    };
                    __gc class Derived : public Base {
                    virtual void SomeVirtualFunc tion()
                    {Console::Write Line(L"Derived" );}
                    };


                    int _tmain()
                    {
                    Base* handle = new Derived();
                    handle->SomeAccessible Function();
                    return 0;
                    }

                    Did they introduce this "feature" in CLR 2.0? That would be very
                    strange, indeed.

                    Comment

                    • Alexei

                      #11
                      Re: VC++ 2005: private virtual functions

                      Nemanja Trifunovic wrote:[color=blue]
                      > Yep, just noticed this in the C++/CLI spec. Actually, I pretty much
                      > like this "controlled virtuality". Just have no idea why to disable
                      > private virtual functions. Any clues?[/color]

                      Let me take a wild guess. Interoperabilit y with other .NET languages?


                      Comment

                      • Nemanja Trifunovic

                        #12
                        Re: VC++ 2005: private virtual functions

                        And the same code on VC++2005 with /clr:oldsyntax gives the following
                        warning:

                        ..\PrivateVirtu al.cpp(46) : warning C4445: 'void
                        Base::SomeVirtu alFunction(void )' : in a managed type a virtual method
                        cannot be private
                        ..\PrivateVirtu al.cpp(54) : warning C4445: 'void
                        Derived::SomeVi rtualFunction(v oid)' : in a managed type a virtual
                        method cannot be private

                        But it works just fine!!!

                        Hehehe, is it weird or what? I'm gonna start ILDasm now to see what's
                        going on...

                        Comment

                        • Nemanja Trifunovic

                          #13
                          Re: VC++ 2005: private virtual functions

                          Hmmm.. here's the difference:

                          "/clr:oldsyntax":

                          ..method private virtual instance void SomeVirtualFunc tion() cil
                          managed
                          {
                          ....

                          "/clr":

                          ..method private hidebysig strict virtual
                          instance void SomeVirtualFunc tion() cil managed
                          {

                          So the difference is "hidebysig strict" part. AFAIK hidebysig is
                          ignored by runetime and is used only by tools, but what the heck is
                          "strict"? I don't remember seing it before...

                          Comment

                          • Ronald Laeremans [MSFT]

                            #14
                            Re: VC++ 2005: private virtual functions

                            Nemanja Trifunovic wrote:[color=blue]
                            > Hmmm.. here's the difference:
                            >
                            > "/clr:oldsyntax":
                            >
                            > ..method private virtual instance void SomeVirtualFunc tion() cil
                            > managed
                            > {
                            > ....
                            >
                            > "/clr":
                            >
                            > ..method private hidebysig strict virtual
                            > instance void SomeVirtualFunc tion() cil managed
                            > {
                            >
                            > So the difference is "hidebysig strict" part. AFAIK hidebysig is
                            > ignored by runetime and is used only by tools, but what the heck is
                            > "strict"? I don't remember seing it before...
                            >[/color]
                            It means exactly what this thread is about: It prevents a private member
                            function from being overriden in a derived class. The reason the CLR
                            added this (and all the Microsoft languages emit this) is that the
                            design of the BCL and FX and common design pattersn in .NET make this a
                            security issue. Many base classes base security and threat model
                            analysis on the fact that a derived class cannot be inserted and change
                            behavior in the base class (like validation) that needs to bge immune to
                            being changed by further derived classes.

                            Ronald Laeremans
                            Visual C++

                            Comment

                            • Brandon Bray [MSFT]

                              #15
                              Re: VC++ 2005: private virtual functions

                              Nemanja Trifunovic wrote:[color=blue]
                              > Yep, just noticed this in the C++/CLI spec. Actually, I pretty much
                              > like this "controlled virtuality". Just have no idea why to disable
                              > private virtual functions. Any clues?[/color]

                              Private virtual functions are still useful for one scenario. In ref classes,
                              in order to override a virtual function, you have to have access to call it.
                              Since a private virtual function can never be called from outside the class,
                              it can never be overridden. Thus, to make the compiler stop issuing a
                              diagnostic for the private virtual function, you can use the "sealed"
                              keyword.

                              Now, virtual functions are also used to implement interface contracts. So,
                              if you want to implement an interface without changing the API exposed
                              directly from the type, you can implement the funtion with a private sealed
                              virtual function.

                              The last thing to bring up is why overriding a virtual function to which you
                              do not have access is a security issue in ref classes but not native
                              classes. For ref classes, types can be derived accross assembly boundaries.
                              Inheriting native classes have never been supported across DLL boundaries
                              with any fidelity. Many times a ref class would make its virtual functions
                              "internal" because they were only needed inside the assembly. In version 1.0
                              of the CLR, any type could override a virtual function. That was intentional
                              because the CLR wanted to support the C++ semantics. The security issue was
                              found after 1.0 shipped, and the strict semantics were introduced in version
                              1.1. C# used the strict semantics in 1.1, and we chose to follow suit with
                              the new C++ syntax in Visual C++ 2005.

                              Hope that helps!

                              --
                              Brandon Bray, Visual C++ Compiler http://blogs.msdn.com/branbray/
                              Bugs? Suggestions? Feedback? http://msdn.microsoft.com/productfeedback/


                              Comment

                              Working...