简体   繁体   English

是否可以从C ++中的基类方法返回派生类?

[英]Is it possible to return a derived class from a base class method in C++?

I would like to do this: 我想这样做:

class Derived;

class Base {
    virtual Derived f() = 0;
};

class Derived : public Base {
};

Of course this doesn't work since I can't return an incomplete type. 当然这不起作用,因为我不能返回不完整的类型。 But neither can I define Derived before base, since I can't inherit from an incomplete type either. 但是我也不能在base之前定义Derived,因为我也不能从不完整的类型继承。 I figure that I could use templates as a workaround (using Derived as a template argument to Base), but it seems a really ugly way of doing things. 我认为我可以使用模板作为解决方法(使用Derived作为Base的模板参数),但这似乎是一种非常丑陋的做事方式。 Might there be another way? 可能还有另一种方式吗?

Elaboration: I'm writing a raytracer, and each Shape class has a function which returns its bounding box. 详细说明:我正在编写一个光线跟踪器,每个Shape类都有一个返回其边界框的函数。 However, I've made the BBox a subclass of Shape, so I can visualize it. 但是,我已经让BBox成为Shape的子类,所以我可以想象它。 Is this bad design? 这是不好的设计吗?

There's nothing wrong with the code in your question. 您的问题中的代码没有任何问题。 This 这个

class Derived;

class Base {
    virtual Derived f() = 0;
};

class Derived : public Base {
    virtual Derived f() {return Derived();}
};

should compile just fine. 应该编译得很好。 However, callers of 'Base::f()' will need to have seen the definition of 'Derived`. 但是,'Base :: f()'的调用者需要看到'Derived`的定义

You could use a pointer (or a reference): 您可以使用指针(或引用):

class Derived;

class Base {
    virtual Derived *f() = 0;
};

class Derived : public Base {
};

But this is code smell to me. 但这对我来说是代码味道。 Why should anybody inheriting from this class need to know about another derived class? 为什么从这个类继承的人需要知道另一个派生类? In fact, why should the base class be concerned with it's derivee's? 事实上,基类为什么要关注它的衍生物呢?

For your situation, you'll need to notice things that mgiht be a signal for bad design. 根据您的情况,您需要注意那些不好的设计信号。 Although it makes sense that your bounding box would derive from Shape , keep in mind, since Shape has a function that returns a bounding box, a bounding box will have a function that returns itself. 虽然你的边界框从Shape派生是有意义的,但请记住,因为Shape有一个函数返回一个边界框,一个边界框将有一个返回自身的函数。

I'm not sure the best solution, but you could make BBox a separate class altogether, and perhaps give it a function akin to: Shape *as_shape(void) const , which would construct a class Box : public Shape with the same dimensions as the bounding box. 我不确定最好的解决方案,但你可以完全将BBox作为一个单独的类,并且可能给它一个类似于: Shape *as_shape(void) const ,它将构造一个class Box : public Shape ,其尺寸与边界框。

I still feel there is a better way, but I'm out of time for now, I'm sure someone else will think of a better solution. 我仍然觉得有更好的方法,但我现在没时间了,我相信别人会想到更好的解决方案。

Why not just do: 为什么不这样做:

class Base {
    virtual Base *f() = 0;
};

Your notion about templates wasn't necessarily a bad one. 你对模板的看法不一定是坏的。 What you describe is called the Curiously Recurring Template Pattern . 您描述的内容称为奇怪的重复模板模式

An example: 一个例子:

#include <iostream>

template <typename T>
struct Base
{
    virtual T* foo() = 0;
};

struct Derived : Base<Derived>
{
    virtual Derived* foo() { return this; }
};

I'd go with returning a pointer to a Base, so that Base doesn't need to know about Derived or anything else that comes along later: 我将返回指向Base的指针,以便Base不需要知道Derived或后来出现的任何其他内容:

class Base {
  virtual Base *f() = 0;
};

class Derived : public Base {
  virtual Base *f();
};

Base *Derived::f() {
  Derived *r = new Derived;
  return r;
}

As others have pointed out, the code sample you have can be made to work, but that you probably mean to return a pointer to the base class from f() . 正如其他人所指出的那样,你可以使你的代码示例工作,但你可能意味着从f()返回一个指向基类的指针。

In your elaboration, you mention that the bounding box is a subclass of shape, but there is a problem: 在您的详细说明中,您提到边界框是形状的子类,但是存在一个问题:

class Shape{
    virtual Shape* getBoundingBox() = 0;
};

class Square: public Shape{
    virtual Shape* getBoundingBox();
};
class BBox: public Shape{
    virtual Shape* getBoundingBox(); // Whoops! What will BBox return?
};

Lets move some of the responsibilities around: 让我们解决一些责任:

class Shape{
    virtual void draw() = 0; // You can draw any shape
};
class BBox: public Shape{
    virtual void draw(); // This is how a bounding box is drawn
};

class BoundedShape: public Shape{
    virtual BBox* getBoundingBox() = 0; // Most shapes have a bounding box
};

class Square: public BoundedShape{
    virtual void draw();
    virtual BBox* getBoundingBox(); // This is how Square makes its bounding box
};

Your application will now probably need to hold collections of BoundedShape* and occasionally ask one for its BBox* . 您的应用程序现在可能需要保存BoundedShape*集合,并偶尔询问其中的BBox*

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否可以从C ++的派生类中调用基类中的方法? - is it possible to call a method in the base class from a derived class in c++? C ++如何从基类调用派生类中的方法 - C++ how to call method in derived class from base class 基类c ++中可互换的派生类方法 - interchangeable derived class method from base class c++ C ++基础和派生类方法的麻烦 - C++ base and derived class method trouble 从抽象基类派生的C ++包装器类,并在另一个也从抽象基类派生的类中调用方法 - C++ wrapper class that is derived from an abstract base class and calls a method in another class that is also derived from the abstract base class 在派生类 C++ 中使用 from base - Using from base in derived class C++ C ++基类是否可能具有带有派生类的参数的函数 - C++ Is it possible that the base class has a function with a parameter of the derived class C ++重载运算符返回派生类对象而不是基类 - C++ overloaded operator to return the derived class object not the base class 使用派生的 class C++ 返回基 class 共享指针 - Return Base class shared pointer using derived class C++ 无法在C ++的派生类中重载基类方法 - Cannot overload base class method in derived class in C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM