locked
WinRT C++ interface inheritance problem

    Question

  • I finally decided to use inheritance in my WinRT C++ library, by exposing interface, such as
    	public interface class IA 
    	{
    		property int ID { int get(); }
    	};
    	ref class A : IA 
    	{
    	public:
    		virtual property int ID { int get() { return 0; } }
    	};
     
    	public interface class IB : IA {};
    	ref class B : A, IB {};
     
    	public ref class Create sealed {
    	public:
    		static IB^ CreateB() { return ref new B(); }
    	};
    

    However when I try to compile that code I got the following error messages:
    1>c:\dev\tests\windowsruntimecomponent1\windowsruntimecomponent1\class1.h(16): error C3766: 'WindowsRuntimeComponent1::B' must provide an implementation for the interface method 'int WindowsRuntimeComponent1::IA::ID::get(void)'
    1> c:\dev\tests\windowsruntimecomponent1\windowsruntimecomponent1\class1.h(7) : see declaration of 'WindowsRuntimeComponent1::IA::ID::get'
    1>c:\dev\tests\windowsruntimecomponent1\windowsruntimecomponent1\class1.h(16): warning C4570: 'WindowsRuntimeComponent1::B' : is not explicitly declared as abstract but has abstract functions
    1>c:\dev\tests\windowsruntimecomponent1\windowsruntimecomponent1\class1.h(20): error C2259: 'WindowsRuntimeComponent1::B' : cannot instantiate abstract class
     
    Now I can fix it by rewriting B as follows
    	ref class B : A, public IB 
    	{
    	public:
    		virtual property int ID { int get() override { return A::ID; } }
    	};
    

     
    But that's quickly becoming cumbersome with a big hierarchy. Isn't there a way to avoid repeating all parent interface members?

    • Moved by Mike Danes Wednesday, October 16, 2013 7:42 AM C++/CX specific
    Wednesday, October 16, 2013 5:19 AM

Answers

  • Doesn't look like a bug to me. I know nothing about WinRT, but a similar situation would not work in plain vanilla C++, either. A class doesn't override a virtual method of its sibling in the hierarchy, only of its base.

    struct IA {
      virtual int GetID() = 0;
    };
    
    struct A : public IA {
      virtual int GetID() { return 42; }
    };
    
    struct IB : public IA {};
    
    class B : public A, public IB {};
    
    B b;
    // error: can't instantiate an abstract class
    // B doesn't implement IB::GetID

    Think about it this way. Class B has two distinct vtables, one for each of its bases, each with a slot for GetID method. One of these vtables is set to point to A::GetID - but the other one is still missing an entry.


    Igor Tandetnik

    • Marked as answer by Lloyd Wednesday, October 16, 2013 2:51 PM
    Wednesday, October 16, 2013 1:45 PM

All replies

  • To me this looks like a compiler bug, I don't see why it requires you to re-implement IA::ID::get.

    However, I don't have much experience with C++/CX so I'll move this post to the WinStore C++ apps forum, perhaps someone else knows better.

    And for the record, code like this works fine in C++/CLI.

    Wednesday, October 16, 2013 7:42 AM
  • Thanks, I might post it on the bug report pages....

    I guess they were not expecting someone inheritance with WinRT! Seeing as they make it impossible! :/

    Wednesday, October 16, 2013 10:29 AM
  • And thanks! :)
    Wednesday, October 16, 2013 10:50 AM
  • Doesn't look like a bug to me. I know nothing about WinRT, but a similar situation would not work in plain vanilla C++, either. A class doesn't override a virtual method of its sibling in the hierarchy, only of its base.

    struct IA {
      virtual int GetID() = 0;
    };
    
    struct A : public IA {
      virtual int GetID() { return 42; }
    };
    
    struct IB : public IA {};
    
    class B : public A, public IB {};
    
    B b;
    // error: can't instantiate an abstract class
    // B doesn't implement IB::GetID

    Think about it this way. Class B has two distinct vtables, one for each of its bases, each with a slot for GetID method. One of these vtables is set to point to A::GetID - but the other one is still missing an entry.


    Igor Tandetnik

    • Marked as answer by Lloyd Wednesday, October 16, 2013 2:51 PM
    Wednesday, October 16, 2013 1:45 PM
  • " I know nothing about WinRT, but a similar situation would not work in plain vanilla C++, either. A class doesn't override a virtual method of its sibling in the hierarchy, only of its base."

    Hmm, that sounds like a reasonable explanation. I was thinking that since multiple inheritance is not allowed in C++/CX then the C++ rules won't apply.

    I guess we'll have to wait and see what Microsoft says on Connect.

    Wednesday, October 16, 2013 2:37 PM
  • Indeed, I can fix it with virtual inheritance

    struct IA {
    	virtual int GetID() = 0;
    };
    
    struct A : virtual public IA {
    	virtual int GetID() { return 42; }
    };
    
    struct IB : virtual public IA {};
    
    class B : public A, virtual public IB {};
    
    B b;
    

    But WinRT doesn't support virtual inheritance!
    That's what's happening!!
    Thanks!
    Too bad... :~

    Wednesday, October 16, 2013 2:51 PM