具有不同模板类型的子类的多态性

Posted

技术标签:

【中文标题】具有不同模板类型的子类的多态性【英文标题】:polymorphism with sub-classes of different template type 【发布时间】:2019-02-04 12:26:04 【问题描述】:

我有带模板的类,一些类继承自他。 我们想创建父类的实例而不声明其模板类型,并调用返回模板类型的函数。

例子:

class FatherWrap 
    virtual ~FatherWrap() = default;
;

template<typename T>
class FatherClass : public FatherWrap

    virtual T getValue();
;

class SonClass1 : public FatherClass<int>

    int getValue() override;
;

class SonClass2 : public FatherClass<string>

    string getValue() override;
;  

int main()

    FatherWrap* ch = new SonClass1();
    T a = ch->getValue; // What to do instead of T.

【问题讨论】:

FatherClass* ch 无效,因为在显示的示例中没有这样的类FatherClass。它是一个类的模板(FatherClass&lt;int&gt; 是一个类)。 请阅读xy problem 并尝试告诉我们您真正想要实现的目标。您的要求是不可能的,但也许我们可以帮助您解决您实际尝试解决的问题 你的小修改完全改变了代码的含义......我希望你不是在编造这个...... 对不起,但在编辑之后,问题的含义就更不清楚了。而不是T,而是使用int,因为SonClass1::getValue 返回一个int。 (ch-&gt;getValue 应该是ch-&gt;getValue(),不是吗?) 为什么“不知道类型”?在您的示例中,您确实知道类型,并且通常当您必须知道类型时,它并不是真正的多态...... 【参考方案1】:

假设你有:

未参数化(无模板)基类B 一个中间模板类I&lt;T&gt;继承自B 一些派生类D1D2等,每一个都继承自I的特化

您想根据B 编写一些代码。你可以这样做——但你必须限制自己使用B 定义的API。 B 的方法可以是虚拟的,I&lt;T&gt;Dx 中这些方法的实现/覆盖可以使用 T 类型,但这些类型不能暴露给只知道 @ 的组件987654333@.

如果您想编写一些使用T 的逻辑,那么该逻辑需要在I&lt;T&gt; 的方法中,或者在本身使用类类型参数化的模板函数中:

template<class U>
U someTypeSpecificLogic(I<U> intermediate) 
    // can call methods that accept/return U here

您不能根据 B 编写依赖于类型 T 的逻辑,因为该类型仅针对子类 I&lt;T&gt; 定义。考虑到您的BB不同 子类,而根本不是I&lt;T&gt;

【讨论】:

【参考方案2】:

您可以完全跳过 FatherWrap 并让基类返回一个变体:

struct FatherClass : FatherWrap 
    virtual std::variant<int, std::string> getValue();
;

struct SonClass1 : FatherClass 
    std::variant<int, std::string> getValue() override 
        return "some text";
    
;

struct SonClass2 : FatherClass 
    std::variant<int, std::string> getValue() override 
        return 95;
    
;   

或者,您可以对任何使用 SonClass 的代码进行模板化:

struct SonClass1  // no parent.
    std::string getValue() 
        return "some text";
    
;

struct SonClass2  // no parent.
    int getValue() 
        return 95;
    
;

template<typename T>
void useSonClass(T& son) 
    // value may be int or string.
    auto value = son.getValue();


int main() 
    SonClass1 sc1;
    SonClass2 sc2;

    useSonClass(sc1);
    useSonClass(sc2);

如果你想包含它,只需使用一个变体:

int main() 
    std::variant<SonClass1, SonClass2> sc = SonClass2;

    std::visit(
        [](auto& sc)  useSonClass(sc); ,
        sc
    );

【讨论】:

以上是关于具有不同模板类型的子类的多态性的主要内容,如果未能解决你的问题,请参考以下文章

模板模式介绍

具有多态模板参数的多态模板类

面向对象编程 多态

C++ 抽象类模板 + 特定类型的子类 = 链接器有问题

C++多态模板类,模板类型对象的实例化

使用java实现面向对象 第三章