我需要将模板作为函数参数传递,但模板必须接受所有继承的对象。
例如:
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) {...}
的参数?
或者如何解决?
答案 0 :(得分:2)
您想要做的事情不起作用的原因是因为模板类型不遵守typename参数中的继承。
Template<Base> *base
和
Template<Child1> *child
是完全不同的类型。尝试使用一个代替另一个就像尝试将int
传递给具有string
参数的函数。
那就是说,我相信你有两个可行的选择。
Test
成为模板一种选择是将Test
作为模板:
template <typename T>
class Test {
T *pointer;
public:
Test(T *pointer) {...}
};
这将允许Test
对象使用传递给它的任何对象。
或者,通过创建界面并在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) {/* ... */}
};
此方法与用于允许隐式向上转换标准智能指针类型的方法相同。