### 如何從虛函數返回泛型派生類？

#### [英]How to return a generic derived class from a virtual function?

I am writing a program that creates and manipulates shapes. The section of code I am having a problem with is below, specifically the return type of the virtual function translate in the polygon class. (this has been reduced for compactness)

``````    class polygon{
public:
virtual ~polygon(){};
virtual class polygon translate() {};
};

class Itriangle : public matrix, polygon{
private:
vector <matrix> vertices;  // vector of matrices
double centrex;
double centrey;
double sides;
public:
//Constructors (default/p const(points)/p const(centre and lengths))
Itriangle(){};

//Destructor
~Itriangle(){};

//Functions from interface

Itriangle translate(class matrix &m){
. . .
Itriangle translated (transCx, transCy, a, b, c);
return translated ;
}
``````

I then go on to derive several other shapes from the polygon class.

The problem I am having with it is that I want the translate function to be able to return any class that is derived from polygon.

I have tried to use points and a template but I am unsure about both.

Any help would be great.

## 1 个解决方案

3

### You're referring to a notion that's called covariant return type.

Since a return type of a function is not a part of its signature you can return a derived type of a base's return type in a polymorphic method as long as its a pointer or a reference.

In your case, a pointer (or a reference) to Itriangle.

``````class polygon {
public:
polygon *translate(class matrix &m) {
return new polygon(...);
}
};

class Itriangle : public matrix, polygon {
public:
Itriangle *translate(class matrix &m) {
return new Itriangle(...);
}
};
``````

Note that it can't be created on the `translate` method's stack, if you want to return it back. Meaning, you'll have to allocate it using `new`.

In general a reference is also possible for achieving this but in your case since the `ITriange` is created inside the `translate(...)` method, it would be problematic (whether it is created on the stack and the reference would point to unallocated memory, or it is allocated on the heap and no one knows it needs to be deleted since it's a reference).
If for example, you were returning a member of the class, then you would be able to use a reference.

I've created a dummy app for you to see it in action:

``````#include <iostream>

using namespace std;

class polygon {
public:
virtual polygon *translate(int x) {
cout << "polygon!" << endl;
return new polygon();
}
};

class Itriangle : public polygon {
public:
Itriangle *translate(int x) {
cout << "triangle!" << endl;
return new Itriangle();
}
};

int main() {
polygon p;
Itriangle t;
polygon &pt = t;

p.translate(1);
t.translate(2);
pt.translate(3);
}
``````

This prints:

polygon!
triangle!
triangle!

By the way, I noticed an error in your code.

your `Itriangle` is defined:

``````class Itriangle : public matrix, polygon {
...
};
``````

which means you're privately inheriting polygon. That is very rarely what you want to do.
I'm guessing you ment:

``````class Itriangle : public matrix, public polygon {
...
};
`````` 