【问题标题】:Is the template instantiation of a subclass polymorphic with a specialization of an interface是具有接口特化的子类多态的模板实例化
【发布时间】:2023-03-31 02:56:01
【问题描述】:

我知道这是一种非常令人困惑的提问方式,所以让我解释一下我的意思。我有一个非常简单的界面。

为了争论,我们假设它看起来像:

class Interface 
{
    public:
    virtual ~Interface() = default;
    virtual someMethod() = 0;
};

我有一个类是 mixin、decorator 或 CRTP,但我不确定适用什么术语

template< typename interface_t > 
class Disablable: public interface_t
{
    public:
    ~Disablable() override = default;
    setDisable(const bool shouldDisable) { mDisabled = shouldDisable; }

    someMethod() override 
    {
        if(mDisabled) return;
        interface_t::someMethod();
    }

    private:
    bool mDisabled = true;
};

我的问题是多态性如何与这个装饰器交互。假设我想从Interface 动态转换为Disablable&lt;Interface&gt;,我的具体实例Disablable&lt;Interface&gt;吗?

例如,假设我有一个实现

class ConcreteImplementation: public Interface
{
    void someMethod() override 
    {
        std::cout << "I printed to cout" << std::endl; 
    }
};

在代码的其他地方我实例化了一个禁用,因此,

std::unique_ptr<Interface> pInterface(new Disablable<ConcreteImplementation>());

有没有办法将pInterface 解释为Disablable

基本上,这是真的吗: dynamic_cast&lt;Disablable&lt;Interface&gt;&gt;(new Disablable&lt;ConcreteImplementation&gt;) != nullptr?

换一种方式问,如果Derived 是一个 Base,是一个Decorated&lt;Derived&gt; 一个Decorated&lt;Base&gt;

【问题讨论】:

  • 我没有看到你从上面的代码中得到任何东西。您的示例中是否缺少某些内容?
  • 好吧,Disposable 是一个装饰器。如果是 CRTP,则基类将通过模板参数了解派生类,而不是从模板参数派生的派生类。

标签: c++ polymorphism crtp dynamic-cast


【解决方案1】:

假设我想从Interface 动态转换为Disablable&lt;Interface&gt;,我的具体实例化是否会是Disablable&lt;Interface&gt;

您的Disablable&lt;T&gt; 派生自T。因此,如果您有一个指针或对Disablable&lt;Interface&gt; 对象的Interface 子对象的引用,那么您可以将此Interface 指针或对指针的引用或对Disablable&lt;Interface&gt; 实例的引用。当然,这只有在您的 Interface 指针或引用确实确实引用了 Disablable&lt;Interface&gt;Interface 子对象时才有效。

基本上,这是真的吗: dynamic_cast&lt;Disablable&lt;Interface&gt;&gt;(new Disablable&lt;ConcreteImplementation&gt;) != nullptr?

没有。 ConcreteImplementation 派生自 Interface,而不是 Disablable&lt;Interface&gt;Disablable&lt;ConcreteImplementation&gt; 派生自 ConcreteImplementation,后者派生自 Interface,而不是 Disablable&lt;Interface&gt;

换一种方式问,如果Derived 是一个 Base,是一个Decorated&lt;Derived&gt; 一个Decorated&lt;Base&gt;

没有。假设Decorated&lt;T&gt; 派生自T,则Decorated&lt;Base&gt; 派生自Base。所以Decorated&lt;Base&gt; BaseDecorated&lt;Derived&gt; 将是 Derived也是 Base,但 不是Decorated&lt;Base&gt;

模板和运行时多态之间没有特殊的关系或交互。类模板是可以从中实例化类类型的模板。类模板可以是多态类类型的模板。所以类模板的实例可以是多态类型。但这并没有改变同一个类模板的不同实例是不相关类型这一事实。如果Blub 是一个类模板,那么Blub&lt;A&gt;Blub&lt;B&gt; 之间通常没有is-a 关系,即使AB 之间存在一个关系。当Blub&lt;A&gt; 被实例化时,所发生的一切就是A 类型被替换到Blub 的定义中。这样做的结果与您自己编写一个具有相应定义的新类一样。

除此之外,可能应该注意的是,如果您发现自己想要执行向下转换,即从基指针转换为指向更派生类型的指针,通常应该将其视为存在的线索may be something not optimal about the overall design

【讨论】:

  • 啊,你是对的!很抱歉,我的示例没有在 Disablable 中包含继承(这就是 CRTP 的原因,对吧?)。我已经用该更改编辑了我的问题(对不起)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多