【问题标题】:Static method definition delegated to derived class (c++)委托给派生类的静态方法定义 (c++)
【发布时间】:2011-06-19 13:40:25
【问题描述】:

去年我看到了一些源代码 (C++),它的作者在基类中声明了静态函数,但将其定义留给了派生类。我记得有一个限制,只允许一个派生类定义上述静态函数。

我知道重写静态方法是不可能的,但是这个技巧正是我所需要的。我只是无法让它在我的代码中工作:) 有人知道这个功能吗?

让我们看看为什么这会有用。假设我们有一些基类(Shape)和它的派生类(Circle、Triangle...)。假设 Shape 是我核心架构的一部分,派生类被视为插件。我不想在未来改变我的核心架构。所以我们有:

class Shape
{
    //other stuff here
    static Shape* Factory();
}

class Circle:Shape
{
    //other stuff here
    static Shape* Factory();
}

Shape 是一种抽象类,它不会实现工厂方法。方法由一个(并且只有一个)派生类实现。在实现派生类将返回自己的新实例,所以它只是一个工厂方法。这个技巧允许它的作者通过以下方式在客户端类中使用这个静态方法:

class Client
{
    public Shape* shape;
    public Client();
    //other stuff here
}

在构造函数的实现中,他有类似的东西:

Client::Client()
:shape(Shape::Factory())
{        
}

通过这种方式,他能够实例化“正确”的形状推导,而无需更改引擎中的核心类。当他想在核心类中使用其他形状时,他只需要在该派生类中定义静态工厂方法(并删除其他派生类中的现有方法)。

这样我们就有了某种“静态多态性”。我在网上找不到有关此技术的任何信息。它甚至有名字吗?如果这样的事情可以用 C# 语言实现,我特别感兴趣? :)

提前致谢,抱歉我的英语不好。

【问题讨论】:

    标签: c++ methods static


    【解决方案1】:

    在我看来,您正在尝试做的事情听起来有点混乱。感觉就像是一个工厂类、一个单例类的组合,然后试图将它们全部压缩回您的结果类层次结构中。

    我能想到的最简单(不一定是最好)的解决方案是忘记使用Circle::Factory()Shape::Factory(),而只需拥有一个名为get_default_shape() 的免费函数。

    class Shape
    {
    };
    
    class Circle: public Shape
    {
    };
    
    Shape * get_default_shape()
    {
      return new Circle;
    }
    
    Client::Client()
    :shape(get_default_shape())
    {
    }
    

    这方面的好处是它唯一需要包含 Circle.h 的 get_default_shape 实现,所有定义需要的是 Shape 类的前向声明。

    【讨论】:

    • 你的解决方案很好,但我想让基类和派生类对自己负责,除了隐藏派生类的实现。但我猜你使用隔离工厂方法(获取默认形状)的方式也应该可以完成工作:) 谢谢。
    【解决方案2】:

    嗯。我没有看到你描述的确切内容。可能是您引用的那段代码在包含您的派生类的 cpp 文件中定义了基类静态函数。

    // definition of Circle class
    .....
    
    Shape* Shape::Factory()
    {
         return new Circle();
    }
    

    这在这个例子中没有用,但如果你想隐藏一个类的实现并且只发布一个抽象基类(以减少编译时依赖),它可能是一个有用的技巧。如果基类和派生类不在同一个 dll/exe 中,它将不起作用。

    在 C# 中可以通过使用 IOC 框架、使用泛型或通过在基类中注册工厂 delegate 来实现类似的事情。我倾向于更喜欢泛型和委托。

    【讨论】:

    • 是的,静态方法是在派生类的cpp文件中定义的。这正是我想要实现的目标:) 但我无法让它在我的代码中工作,因为当我将静态类定义放在派生类 cpp 文件中时,编译器报告说基类不可访问。我想我的问题的答案是:“检查两个类是否在同一个 dll/exe 中”? :) 你能告诉我更多关于 C# 委托和泛型版本的相同技巧吗?提前致谢。
    • 尝试用一个简单而干净的测试项目进行重现,然后发布结果。如果你想了解 C#,想想你的问题是什么,编写代码来演示它并将它作为一个新问题发布。
    猜你喜欢
    • 2016-09-08
    • 2010-10-10
    • 2010-09-22
    • 2012-05-24
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多