【问题标题】:Create a generic class with multiple inheritance input types创建具有多个继承输入类型的泛型类
【发布时间】:2020-10-29 08:17:25
【问题描述】:

我想创建一个父类,它定义了一个我可以在继承中重写的通用虚函数,并且我想在每个孩子中更改输入类型。我尝试创建一个模板函数,但我发现如果您尝试将其设为虚拟,模板函数将无法编译。我有一个想法,在父类中模板化一个变量,这样就不必在这个变量上使用继承,然后在子类中,使用特定版本的变量在覆盖函数中做一些事情。

class a {
    virtual void doSomething() {
        //nothing in parent
    }

    template<typename T>
    T input;

    template<typename T>
    void SetInput(T i) {
        this->input = i;
    }
};

class b : a {
    virtual void doSomething() override {
        float test = this->input;
    }
};

class c : a {
    virtual void doSomething() override {
        char test = this->input;
    }
};

class d : a {
    virtual void doSomething() override {
        int test = this->input;
    }
};

void main(){
    std::vector<a> allNodes(3);
    b t1;
    t1.SetInput<float>(41.5f);
    c t2;
    t2.SetInput<char>('b');
    d t3;
    t3.SetInput<int>(3);
    allNodes[0] = t1;
    allNodes[1] = t2;
    allNodes[2] = t3;

    for (a node : allNodes) {
        node.doSomething();
    }
}

但是从现在开始,这个想法不再编译了,因为它告诉我需要在father中,在SetInput()函数中定义模板的类型,当我要设置它时。

如果你有什么想法,请告诉我。谢谢

【问题讨论】:

  • 您是否希望char test = this-&gt;input; 生成input 类型的char 以及其他类似的类型?
  • 我希望有一种通用的方式来调用基本方法和创建多个不同输入类型的子类的可能性,并且只需要一个调用就可以做出特定的事情

标签: c++ templates inheritance polymorphism c++17


【解决方案1】:

这是一个让很多人感到困惑的典型问题,可以通过以下步骤非常简单地完成:

  1. 在不知道对象类型的情况下制作一个包含你要调用的常用函数的接口,我将其命名为Doable

  2. 创建一个从接口Doable派生的模板类,我将其命名为MyType,其中包含模板化的数据成员和操作get()&set()。重要提示:还覆盖Doable中的纯虚函数

  3. 将模板的函数dosomething() 专门用于您想在程序中使用的所有数据类型。

== 宾果游戏 ==

#include <iostream>
#include <string>
#include <vector>

class Doable {
public:
    virtual ~Doable() = default;
    virtual void dosomething() = 0;
};

template <typename T>
class MyType : public Doable {
public:
    T data_;
    void set(const T& d) {
        data_ = d;
    }
    T get() const {
        return data_;
    }
    void dosomething() override { }
};


template<>
void MyType<int>::dosomething() {
    std::cout << "int: " << data_ << std::endl;
}

template<>
void MyType<char>::dosomething() {
    std::cout << "char: " << data_ << std::endl;
}

template<>
void MyType<float>::dosomething() {
    std::cout << "float:" << data_ << std::endl;
}

int main(){
    std::vector<std::unique_ptr<Doable>> a;
    std::unique_ptr<MyType<float>> b1(new MyType<float>);
    b1->set(41.5f);
    a.push_back(std::move(b1));

    std::unique_ptr<MyType<char>> b2(new MyType<char>);
    b2->set('b');
    a.push_back(std::move(b2));

    std::unique_ptr<MyType<int>> b3(new MyType<int>);
    b3->set(3);
    a.push_back(std::move(b3));

    for (auto& ptr : a){
        ptr->dosomething();
    }
}

输出是:

float:41.5
char: b
int: 3

【讨论】:

  • 如果这解决了您的问题,请接受答案,以便我们知道您在寻找什么。
【解决方案2】:
  1. 变量模板不允许作为类的非静态成员,您必须使用类模板。
  2. 虚函数模板也是不允许的。您必须通过非虚函数模板调用非模板虚函数

所以你应该同时使用一个通用基类作为一个多态类和一个类模板来存储不同类型的值:

template<typename T>
class B;

class A{
public:
    virtual ~A() = default;
    template<typename T>
    void set(T a){
        dynamic_cast<B<T>*>(this)->input = a;
    }
    template<typename T>
    T get() const{
        return dynamic_cast<B<T>*>(this)->input;
    }
    virtual void dosomething() = 0;
};

template<typename T>
class B : public A{
public:
    T input;
    virtual ~B() = default;
};

class C : public B<float>{
public:
    virtual ~C() = default;
    virtual void dosomething() override{
        std::cout << input << std::endl;
    }
};

class D : public B<int>{
public:
    virtual ~D() = default;
    virtual void dosomething() override{
        std::cout << input << std::endl;
    }
};

int main(){
    std::vector<A*> a;
    C* c = new C;
    c->set(12.3f);
    a.push_back(c);
    D* d = new D;
    d->set(1);
    a.push_back(d);
    for (auto ptr : a){
        ptr->dosomething();
    }
    // output:
    // > 12.3
    // > 1
    delete c;
    delete d;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2015-09-15
    相关资源
    最近更新 更多