模板参数

时间:2016-06-04 23:13:35

标签: c++ templates inheritance parameters parameter-passing

我需要将模板作为函数参数传递,但模板必须接受所有继承的对象。

例如:

template <class T>
class Template {
public:
    Template() {}
};

// IMPORTANT: must accept all children of "Base"
class Test {
    Template<Base> *pointer;
public:
    Test(Template<Base> *pointer) {...}
};


main() {
    Template<Base> *base = new Template<Base>();
    Template<Child1> *child = new Template<Child1>();

    Test *test1 = new Test(base);    // WORKING
    // NEXT LINE IS IMPORTANT:
    Test *test2 = new Test(child);   // ERROR: no matching function for call to 'Test::Test(Template<Child1>*&)'
}


class Base {...};
class Child1 : public Base {...};
class Child2 : public Base {...};
..

我需要最有效的方法,如何在“Test”类中​​存储模板,这将接受所有子类。我有很多孩子班。

1)是否可以在参数中为Child类进行一些向上转换(static_cast)?在“模板”里面或“测试”类里面使用它会很好。不是,在创建新的“Test”对象时,因为会有很多新对象。

2)或者传递没有模板参数Test(Template *pointer) {...}的参数?

或者如何解决?

2 个答案:

答案 0 :(得分:2)

您想要做的事情不起作用的原因是因为模板类型不遵守typename参数中的继承。

Template<Base> *base

Template<Child1> *child

是完全不同的类型。尝试使用一个代替另一个就像尝试将int传递给具有string参数的函数。

那就是说,我相信你有两个可行的选择。

#1使Test成为模板

一种选择是将Test作为模板:

template <typename T>
class Test {
    T *pointer;
public:
    Test(T *pointer) {...}
};

这将允许Test对象使用传递给它的任何对象。

#2使用接口

或者,通过创建界面并在Template中实现该界面,您可以将界面传递给Test类:

/**
 * Interface that declares the virtual methods that
 * will be used by your Test class.
 */
class ITemplate {
public:
    virtual ~ITemplate() {}

    // Define your methods here.
    virtual void Foo() = 0;
    virtual void Bar() = 0;
    virtual void Baz() = 0;
}

/**
 * Concrete ITemplate implementation.
 */
template <class T>
class Template : public ITemplate {
public:
    Template() {}
    virtual ~Template() {}

    virtual void Foo() override {}
    virtual void Bar() override {}
    virtual void Baz() override {}

};

class Test {
    ITemplate *pointer;
public:
    Test(ITemplate *pointer) {...}
};

这样做的好处是,您可以在不影响Template类的情况下修改Test类,因为Test类可以使用ITemplate接口而不是具体对象。这样做的缺点是你会产生虚函数查找的成本,如果你想编写非常有效的代码,这可能是不可取的。

答案 1 :(得分:1)

  

1)是否可以在参数中为Child类进行一些向上转换(static_cast)?在&#34;模板&#34;中使用它会很好。或者#34;测试&#34;类。不是,在创建新的&#34;测试&#34;对象,因为会有很多新对象。

我并不完全明白你的建议。它不可能将不相关的指针投射到另一个指针。

  

2)或者在没有模板参数的情况下传递参数

没有。模板不能是函数参数。

您可以做的是将Template<T>隐式转换为Template的其他实例:

template <class T>
class Template {
public:
    // ...

    template<class U>
    Template(const Template<U>&);
};

根据转换构造函数的实现方式,它可能会对U施加限制。

此外,如果您要在Template<Base>内存储Test实例而不是指针:

class Test {
    Template<Base> member;
    // ...
};

然后,您可以接受Template<Base>按值(复制)或通过rvalue-reference(移动)到构造函数。 Template<Child>会隐式转换为Template<Base>

class Test {
    Template<Base> member;
public:
    Test(Template<Base> argument) {/* ... */}
};

此方法与用于允许隐式向上转换标准智能指针类型的方法相同。