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

[英]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.

我遇到的問題是我希望translate函數能夠返回派生自多邊形的任何類。

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

我試圖使用點和模板,但我不確定兩者。

Any help would be great.

任何幫助都會很棒。

1 个解决方案

#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.

在你的情況下,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.

請注意,如果要將其返回,則無法在translate方法的堆棧上創建它。意思是,你必須使用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.

一般來說,也可以通過引用來實現這一點,但是在你的情況下,因為ITriange是在translate(...)方法中創建的,所以它會有問題(無論是在棧上創建還是引用都指向未分配的內存,或者它在堆上分配,沒有人知道它需要被刪除,因為它是一個參考)。例如,如果您要返回該類的成員,那么您將能夠使用引用。


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:

你的Itriangle定義如下:

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 {
    ...
};

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2015/04/15/72faa8090d1c5abe1e3f59ac140ba7e0.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com