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

时间:2019-02-04 12:26:04

标签: c++ class templates polymorphism abstract-class

我有带有模板的课程,有些课程是从他那里继承的。 我们要创建父类的实例而不声明其模板类型,然后调用一个返回模板类型的函数。

示例:

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.
}

2 个答案:

答案 0 :(得分:3)

假设您拥有:

  • 未参数化(无模板)的基类B
  • I<T>继承的中间模板类B
  • 某些派生类D1D2等,每个类都继承自I的专业化

您想用B来编写一些代码。您可以做到这一点-但您必须限制自己使用B定义的API。 B的方法可以是虚拟的,I<T>Dx中这些方法的实现/覆盖可以使用类型T,但是这些类型不能公开唯一了解B的组件。

如果您想编写一些使用T的逻辑,则该逻辑必须在I<T>的方法中,或者在本身使用类类型进行参数化的模板函数中: / p>

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

您不能使用取决于类型B的{​​{1}}来编写逻辑,因为该类型仅是为子类T定义的。考虑到I<T>B不同子类,而根本不是B

答案 1 :(得分:0)

您可以完全跳过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
    );
}