locked
Overriding a generic method that has a generic return type. RRS feed

  • Question

  • I'm having trouble overriding a generic method in a base class, where the generic method returns a generic type.  The compiler complains that "overriding virtual function return type differs from 'T Base::GetData(void)'.  It's probably something obvious but I just can't seem to figure it out.  Below is a sample of what I am trying to do.  Any help would be greatly appreciated.

    public ref class Base
    {
        generic <typename T> where T : SpecificObject
        virtual T GetData()
        {
            // Do some work and return a T.
        };
    
        generic <typename T> where T : SpecificObject
        virtual void SetData(T data)
        {
            // Use the provide data to do something.
        };
    };
    
    generic <typename U>
    public ref class Derived : Base
    {
        // Overriding SetData works just fine.
        generic <typename T>
        virtual void SetData(T data) override
        {
            // Do some setting specific to U.
        };
    
        // Overriding GetData results in C2553: 
        // "overriding virtual function return type differs 
        // from 'T Base::GetData(void)'" error.
        generic <typename T>
        virtual T GetData() override
        {
            // Do some work specific to U and return a T.
        };
    };
    If I change GetData to return a specific type, everything works fine.  I also get this error whether or not I add constraints to T in the Base::GetData.  I am thoroughly confused. 

    Thanks again for any help you may have to offer.
    Tuesday, October 20, 2009 4:44 PM

Answers

  • The compiler can't tell whether the T from the base class or the T from the derived class are the same, even if you use the same letter.

    I would change the classes as follows

    generic <typename T>
     public ref class Base
     {
     public:
      virtual T GetData()
      {
        //do stuff
      }
     };

     generic <typename T, typename U>
     public ref class Derived : Base<T>
     {
     public:
      virtual T GetData() override
      {
        //do stuff
      }
     };

    In this case, because you are using the same type in both of the classes, even giving the base class the same type as the derived class then it will work and compile correctly.


    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Marked as answer by ed.downs Tuesday, October 20, 2009 5:08 PM
    Tuesday, October 20, 2009 4:58 PM
  • What you're trying to do is illegal. From the docs for generic functions: "virtual is not allowed since virtual methods may not be generic."

    This also means that while SetData seems to be compiling properly, it's illegal as well. Ideally, you would get a compiler error for defining a virtual generic function in Base.
    • Marked as answer by ed.downs Tuesday, October 20, 2009 5:19 PM
    Tuesday, October 20, 2009 5:06 PM

All replies

  • The compiler can't tell whether the T from the base class or the T from the derived class are the same, even if you use the same letter.

    I would change the classes as follows

    generic <typename T>
     public ref class Base
     {
     public:
      virtual T GetData()
      {
        //do stuff
      }
     };

     generic <typename T, typename U>
     public ref class Derived : Base<T>
     {
     public:
      virtual T GetData() override
      {
        //do stuff
      }
     };

    In this case, because you are using the same type in both of the classes, even giving the base class the same type as the derived class then it will work and compile correctly.


    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Marked as answer by ed.downs Tuesday, October 20, 2009 5:08 PM
    Tuesday, October 20, 2009 4:58 PM
  • What you're trying to do is illegal. From the docs for generic functions: "virtual is not allowed since virtual methods may not be generic."

    This also means that while SetData seems to be compiling properly, it's illegal as well. Ideally, you would get a compiler error for defining a virtual generic function in Base.
    • Marked as answer by ed.downs Tuesday, October 20, 2009 5:19 PM
    Tuesday, October 20, 2009 5:06 PM
  • I guess that makes sense.  I just figured that since the base class didn't have a specific type specified and that the derived class didn't have a specific type specified, that the compiler could figure out that the type used in a call to the derived would be the same in the call to the base.  I think the above works in C#, which I'm more used to. 

    I didn't really define any type specific data in the base class, because I wanted the base class to have as little type specific data as possible and the derived classes would then provide extra type specific details and methods.  Having the generic less base class would allow users who don't care about type specifics to work with Base, while those interested in more specific functionality could used derived versions.  I'm attempting to create an easy to use, object oriented wrapper around a bunch of old native libraries that don't do anything in a object oriented fasion and the above was an easy way to get around some of the native weirdness. 

    I guess I'll have to find a different way.  Thanks so much!
    Tuesday, October 20, 2009 5:08 PM
  • Thanks for the reference to that document.  Sometimes the major differences between how C++/CLI and C# implement things is painful.  I'm learning slowly.   Thanks again.

    Tuesday, October 20, 2009 5:19 PM