1

I want to define an abstract base class with a vector of struct variables, and a virtual function to be implemented by derived classes:

class TestFather {

private:
    struct myStruct
    {
        // struct definition
    };
    vector<myStruct> myStructVect;

public:
    virtual vector<myStruct> get_myStructVect() = 0;
};

but when I write the derived class:

#include "TestFather.h"

class TestSon : public TestFather{

private:
    struct myStruct
    {
        // struct definition
    };
    vector<myStruct> myStructVect;

public:
    vector<myStruct> get_myStructVect();
};

I get this error:

invalid covariant return type for ‘virtual std::vector<ProvaSon::myStruct, std::allocator<ProvaSon::myStruct> > ProvaSon::get_myStructVect()’

Am I doing something wrong or maybe I'm trying to do something that is forbidden by the language?

2
  • Why do you redefine twice myStruct? Commented Apr 12, 2011 at 16:46
  • Ok, that was the "human error" :) Commented Apr 13, 2011 at 7:53

5 Answers 5

4

The two myStruct types are totally unrelated. This means that you're trying to override TestFather::get_myStructVect() and have it return a completely different type. This is not allowed.

Sign up to request clarification or add additional context in comments.

2 Comments

Not true on the last point - because he's returning vectors of them, not pointers to them.
Yup - just because they have the same name doesn't mean thy're the same!
3

You don't have to redefine the struct in TestSon, and you also can't do this. The caller of fatherptr->get_myStructVect statically gets a vector<TestFather::myStruct> back, so the compiler forbids you to override the base class function like that, because the dynamically returned object would potentially be incompatible with vector<TestFather::myStruct> (who knows what you put into TestSon::myStruct and how vector differs in behavior from the base class vector?).

As for the allowed difference, C++ only allows the derived class return type to be a derived class of the base class return type, and only when the return types are pointers or references.

Comments

2

It's forbidden. Because you've redefined myStruct in your derived class, vector<myStruct> is a different type in the derived class than it is in the base class. They are two different myStructs.

You can only change the return type of that virtual function to something inherited from the return type declared in the base class. But vector<TestSon::myStruct> does not inherit from vector<TestFather::myStruct>

Comments

2

It says vector<myStruct> but since you changed myStruct in the child class it's actually two distinct types so each of the two functions thinks its returning a different type. This is only allowed for covariant types where the type is related to the actual type of the class containing the function.

Note that you probably shouldn't be returning a class attribute vector by value here anyway.

I can't tell what you really are intending to do, but the nested structures really shouldn't have the same name if they're two different things (and if they're the same, don't redefine it). My first gut reaction is that maybe the parent-child relationship isn't appropriate here. Have you considered other options? If you really need to return a different type in the child and the parent doesn't know about that, then you can't use a virtual interface to do this. You should just give the functions different names so you know what the return type should be.

With more details about your goals a better answer could be provided.

1 Comment

My goal is to define a number of subclasses that have a common data structure, so I think the choice of an interface is appropriate. I want that these classes do different things on the same data, and I want to put some form of restriction on the structure of this data (hence I chose interface).
1

The duplicate private structure is a bit odd in your example. The below compiles fine, for instance:

class TestFather {

protected:
    struct myStruct
    {
        // struct definition
    };
    vector<myStruct> myStructVect;

public:
    virtual vector<myStruct> get_myStructVect() = 0;
};

class TestSon : public TestFather{



public:
    vector<myStruct> get_myStructVect();
};

int main(int argc, char**argv)
{
   TestSon testSon;
}

Note the replacement of private with protected, allowing derived classes access to the parent structure definition and myStructVect storage.

1 Comment

No, it does'nt, g++ returns "undefined reference to `vtable for TestSon'". However, 'protected' is a useful hint.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.