locked
abstract class in Win 8 RTM ?

    Question

  • Hi guys.

    How can i create (and use) my own abstract class with pure virtual methods in RTM ? 

    I need something like:

    public ref class MyParent abstract
    {
      public:
        virtual func() = 0;
    };
    
    public ref class MyClass sealed : MyParent
    {
      public:
        virtual func() { ... }
    };
    
    public ref class MyClass1 sealed : MyParent
    {
      public: 
        virtual func() { ... }
    };

    But i getting:

     'MyParent::func' : cannot introduce a new virtual method as 'public'. Consider making the method non-virtual, or change the accessibility to 'internal' or 'protected private'

    I need it virtual and need it public.

    But OK ... i will make them internal, but now i get:

    A WinRT 'public ref class' must either be sealed or derive from an existing unsealed class

    What !? It cannot be sealed as it's abstract class, and must be public ref class because it's parent for other WinRT classes (WinRT classes cannot inherite from private classes).So i need to ask again ... how can i create my own abstract class in RTM ?

    Thanks for answer.

    Edit: i cannot use DependencyObject as it's intreface and i need to use my classes from several threads (not only one where it was created).


    Friday, August 17, 2012 9:03 AM

Answers

  • http://www.microsoft.com/en-us/download/details.aspx?id=30706 is the RTM migration guide. See the section An unsealed public ref class must have a Windows Runtime base class in its inheritance hierarchy.

    An upcoming document drop should have a bit more info in the Ref classes and Structs (C++/CX) section. Basically it's that the inheritance model in C++/CX is only designed to support XAML object hierarchies -- it is not intended as a general inheritance model ala C++. Outside of XAML UI elements, WinRT hierarchies are required to be flat.

    Friday, August 24, 2012 1:11 AM
    Moderator
  • C++/CX does have a Platform::Object that is similar (not the same) with System::Object in C++/CLI: it is indeed the absolute base of all WinRT types. When you write:

    ref class MyClass // : Platform::Object (redundant)
    {
    };

    The ref-class is implicitly inheriting from Platform::Object. Such a class can be exposed through winmds as a public runtime class as long as you mark it sealed.

    If the ref-class is private, you can inherit from MyClass and create a more complex hierarchy:

    ref class MyDerived: public MyClass 
    {
    };

    But none of the types in this hierarchy can be exposed as public types via winmds, unless the base class is one of unsealed types shipped as part of the Win8 WinRT surface (esentially only XAMLUI types).

    You will notice that C#/VB has the same restrictions when exposing types as WinRT types because it is a restriction of the WinRT contract.

    Hope this helps,
    Marian Luparu
    Visual C++

    Friday, August 24, 2012 5:53 PM

All replies

  • You most likely need to use the override keyword in the derived class method (to indicate that you are overriding the base virtual method).

    And as for your 2nd issue, that's a breaking change in RTM where your public types must be sealed or derive from an existing WinRT type. meaning your abtract type cannot be publicly exposed.  See Steve Home's response here : http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/0adc47ce-aaf7-48fe-a2a9-6f6c7fd20036


    http://blog.voidnish.com

    Friday, August 17, 2012 1:02 PM
  • I've forgot to write override keyword. Main problem i have with is MyParent class. How should i make this class abstract when :
    1. it need to be derived from non-sealed class (like DependencyObject), but i cannot use WinRT object as a parent because they're using interfaces
    2. i need to create/use my classes in several threads (that's why it cannot be derived from UI interface) ?


    Friday, August 17, 2012 1:33 PM
  • Wouldn't making it non-public allow you to declare it abstract without deriving from a WinRT class? It's only the public types that should have that constraint.

    http://blog.voidnish.com

    Friday, August 17, 2012 4:45 PM
  • And yes, cross-thread access is a major problem. Trouble is they put this into RTM so no one could give any feedback. Not sure what the best way to work around this is for now.

    http://blog.voidnish.com

    Friday, August 17, 2012 4:46 PM
  • Yes i can make them private, but then i cannot use them for UI (as Bindable class) as WinRT class cannot inherit from private class :-/.
    Friday, August 17, 2012 5:25 PM
  • So instead of abstract classes, you need to define an interface for UI consumers:

    public interface class  IFileCollection
    {
        property Windows::Foundation::Collections::IVector<T>^ Files;
        Platform::String^  GetFileInfoAsString(T file);
    };
    
    private abstract ref class MediaFileCollection : AnotherBaseType, IFileCollection<MediaFile^>
    {
    public:
        
        virtual Platform::String^  GetFileInfoAsString(MediaFile^ file){return "";}
    };
    
    public ref class WorkingFileCollection : MediaFileCollection
    {
       public:
           Platform::String^ GetFileInfoAsString(MediaFile^ file)
           {return file.Path;}
    }
    

    This allows users to pass around references to implementations of whatever the MyParent type does without needing to know exactly what implementation it is.  Then you can have a private partial implementation class and two public complete implementations that are sealed and that implement the entire interface.  This makes the code feel more COM-ey, I think, but abstract classes are a very peculiar part of C++ that are a primordial implementation of the "interface" mechanic with which most programmers are now very familiar.

    At least I think this is legal in C++/CX in RTM now; don't have a RTM C++ project yet in which to test this.

    Friday, August 17, 2012 6:22 PM
  • Problem is that public ref class in RTM cannot inherite from private class, so
    public ref class WorkingFileCollection : MediaFileCollection
    is denied.
    Friday, August 17, 2012 7:08 PM
  • Perhaps you can try marking the member as protected and the class as internal?  Failing that, the only recourse you might have is to use the pImpl pattern, which the interface implementation classes have just a shallow wrapper where one version points to one implementation and a second points to another.
    Friday, August 17, 2012 7:41 PM
  • http://www.microsoft.com/en-us/download/details.aspx?id=30706 is the RTM migration guide. See the section An unsealed public ref class must have a Windows Runtime base class in its inheritance hierarchy.

    An upcoming document drop should have a bit more info in the Ref classes and Structs (C++/CX) section. Basically it's that the inheritance model in C++/CX is only designed to support XAML object hierarchies -- it is not intended as a general inheritance model ala C++. Outside of XAML UI elements, WinRT hierarchies are required to be flat.

    Friday, August 24, 2012 1:11 AM
    Moderator
  • Steve,

    Is there anything akin to C#'s System.Object class that we can use as a root base class for all inheritors?  C++/CLI had such a thing (because it was indeed based on the CLI; C++ was just the obtuse language that you could use to generate intermediate code).  Does C++/CX not have a comparable infrastructure?  If so, do we just need to implement methods at multiple places in our class hierarchies in order to expose them to JavaScript?

    Friday, August 24, 2012 2:26 AM
  • No, WinRT has an Platform::Object class, but it is sealed to prevent public derivation. The only unsealed classes are in the XAML UI area (e.g. DependencyObject).

    Friday, August 24, 2012 5:20 PM
    Moderator
  • C++/CX does have a Platform::Object that is similar (not the same) with System::Object in C++/CLI: it is indeed the absolute base of all WinRT types. When you write:

    ref class MyClass // : Platform::Object (redundant)
    {
    };

    The ref-class is implicitly inheriting from Platform::Object. Such a class can be exposed through winmds as a public runtime class as long as you mark it sealed.

    If the ref-class is private, you can inherit from MyClass and create a more complex hierarchy:

    ref class MyDerived: public MyClass 
    {
    };

    But none of the types in this hierarchy can be exposed as public types via winmds, unless the base class is one of unsealed types shipped as part of the Win8 WinRT surface (esentially only XAMLUI types).

    You will notice that C#/VB has the same restrictions when exposing types as WinRT types because it is a restriction of the WinRT contract.

    Hope this helps,
    Marian Luparu
    Visual C++

    Friday, August 24, 2012 5:53 PM