c++ - 如何在派生类上强制使用静态成员?

标签 c++ methods static virtual

我有一个基类 Primitive,我从中派生了几个其他类 -- SpherePlane 等。

Primitive 通过纯虚函数在其子类上强制执行某些功能,例如 intersect()intersect 的计算依赖于实例数据,因此将其作为成员方法是有意义的。

我的问题出现在以下方面: 我希望每个派生实例都能够识别其类型,比如通过 std::string type() 成员方法。由于同一类的所有实例都将返回相同的类型,因此将 type() 设为 static 方法是有意义的。因为我也希望每个 Primitive 子类都实现这个方法,所以我也想把它变成一个纯虚函数,就像上面的 intersect() 一样。

但是,C++ 中不允许使用静态虚方法。 C++ static virtual members?Can we have a virtual static method ? (c++) 问类似的问题,但它们不包括在派生类上强制执行该功能的要求。

谁能帮我解决以上问题?

最佳答案

让我们考虑一下。我确定您不仅有 2 个 sublcasses,所以让我们概括一下。

首先想到的是代码重复、可扩展性和封闭性。让我们展开这些:

如果您想添加更多的类,您应该在尽可能少的地方更改代码。

因为intersect操作是可交换的AB相交的代码应该在同一个place 作为 BA 相交的代码,因此将逻辑保留在类本身中是不可能的。

另外,添加一个新类并不意味着您必须修改现有类,而是扩展一个委托(delegate)类(是的,我们将在这里讨论模式)。

这是你当前的结构,我假设(或类似的,可能是 intersect 的返回类型,但现在不重要):

struct Primitive
{
    virtual void intersect(Primitive* other) = 0;
};
struct Sphere : Primitive
{
    virtual void intersect(Primitive* other)
};
struct Plane : Primitive
{
    virtual void intersect(Primitive* other);
};

我们已经决定不希望在 PlaneSphere 中使用相交逻辑,因此我们创建了一个新的 class:

struct Intersect
{
    static void intersect(const Sphere&, const Plane&);
    //this again with the parameters inversed, which just takes this
    static void intersect(const Sphere&, const Sphere&);
    static void intersect(const Plane&, const Plane&);
};

这是您要添加新功能和新逻辑的类。例如,如果您决定添加一个 Line 类,您只需添加方法 intersec(const Line&,...)

请记住,在添加新类时,我们不想更改现有代码。所以我们无法检查您的相交函数中的类型。

我们可以为此创建一个行为类(策略模式),它的行为因类型而异,之后我们可以扩展:

struct IntersectBehavior
{  
    Primitive* object;
    virtual void doIntersect(Primitive* other) = 0;
};
struct SphereIntersectBehavior : IntersectBehavior
{
    virtual void doIntersect(Primitive* other)
    {
        //we already know object is a Sphere
        Sphere& obj1 = (Sphere&)*object;
        if ( dynamic_cast<Sphere*>(other) )
            return Intersect::intersect(obj1, (Sphere&) *other);
        if ( dynamic_cast<Plane*>(other) )
            return Intersect::intersect(obj1, (Plane&) *other);

        //finally, if no conditions were met, call intersect on other
        return other->intersect(object);
    }
};

在我们原来的方法中,我们有:

struct Sphere : Primitive
{
    virtual void intersect(Primitive* other)
    {
        SphereIntersectBehavior intersectBehavior;
        return intersectBehavior.doIntersect(other);
    }
};

一个更简洁的设计是实现一个工厂,以抽象出行为的实际类型:

struct Sphere : Primitive
{
    virtual void intersect(Primitive* other)
    {
        IntersectBehavior*  intersectBehavior = BehaviorFactory::getBehavior(this);
        return intersectBehavior.doIntersect(other);
    }
};

而且您甚至不需要 intersect 是虚拟的,因为它会为每个类都这样做。

如果你遵循这个设计

  • 添加新类时无需修改现有代码
  • 将实现集中在一个地方
  • 仅为每个新类型扩展IntersectBehavior
  • Intersect 类中为新类型提供实现

我敢打赌这可以进一步完善。

关于c++ - 如何在派生类上强制使用静态成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10502114/

相关文章:

c++ - 显示 std::thread 函数传递的错误数据。

c++ - 'char x[]' 是什么意思?

java - 如何在 Android 中编写等待输入的 while 循环?

java - 制作抽奖申请 : fill array with random numbers

c++ - 在给定图像中使用 opencv 进行对象识别

c++ - 每个 g++ 的 minGW 编译警告

file - Yii2 - 日志文件 (app.log) 以及如何访问它们?

java - 尝试在另一个方法中运行方法时出现错误 "This method requires a body instead of a semicolon"

java - 如何在 Java 中安全地写入静态字段?

c - 限制 Linux 静态库中的符号