上次我们已经可以复合(组合)函数了,我们可以写出下面的代码
int main()
{
Comp<int (*)(int), int (*)(int), int, int> fg(f, g);
fg(42);
}
但是,这么繁琐的对象创建,能不能简化一下。我们跟希望能写成这样
int main()
{
Composition<int, int> fg(f, g);
}
怎么做?下面开始完成它!
奇怪,我们希望的写法怎么没指出需要进行复合的那两个函数的类型呢?我们也正是通过“抛弃”他们而简化了创建对象。
其实我们并不是“抛弃”他们,而是把对他们类型的指定交给了模板去推断。而手段就是把构造函数声明为模板。
大概的讲了一下,接下来开始慢慢介绍了。
首先我们可以通过继承的机制来把基类的类型形参传递给派生类,根据这个指导思想我们可以把4个类型形参分开。
而基类的类型是函数接受的参数类型和返回的参数类型。
#ifndef COMP_BASE_H_INCLUDE
#define COMP_BASE_H_INCLUDE
template <typename X, typename Y>
class Comp_base {
public:
virtual Comp_base* clone() const = 0;
virtual ~Comp_base() { }
virtual Y operator() (X) const = 0;
};
#endif
Comp_base<X, Y>的对象表示一个接受参数X并返回Y的任意函数对象,基类存在的意义是为派生类提供类型参数,显然该基类不应该有对象。
接着让Comp<F, G, X, Y>继承类Comp_base<X, Y>
#ifndef COMP_H_INCLUDED
#define COMP_H_INCLUDED
#include "Comp_base.h"
template <typename T, typename G, typename X, typename Y>
class Comp: public Comp_base<X, Y> {
public:
Comp(T, G);
Y operator() (X) const;
Comp_base* clone() const;
private:
T f;
G g;
};
#include "Comp.cpp"
#endif
#include "stdafx.h"
#include "Comp.h"
template <typename T, typename G, typename X, typename Y>
Comp<T, G, X, Y>::Comp(T f0, G g0): f(f0), g(g0) { }
template <typename T, typename G, typename X, typename Y>
Y Comp<T, G, X, Y>::operator()(X n) const
{
return f(g(n));
}
template <typename T, typename G, typename X, typename Y>
Comp_base<X, Y>* Comp<T, G, X, Y>::clone() const
{
return new Comp(*this);
}
然后我们可以创建一个代理Composition(它包含一个指向Comp_base的指针)
#ifndef COMPOSITION_H_
#define COMPOSITION_H_
#include "Comp_base.h"
template <typename X, typename Y>
class Composition {
public:
template <typename T, typename G> Composition(T, G);
~Composition();
Composition(const Composition&);
Composition& operator=(const Composition&);
Y operator()(X) const;
private:
Comp_base<X, Y>* clone() const;
Comp_base<X, Y>* cp;
};
#include "Composition.cpp"
#endif
#include "Composition.h"
template <typename X, typename Y>
template <typename T, typename G>
Composition<X, Y>::Composition(T f, G g):cp(new Comp<T, G, X, Y>(f, g)) { }
template <typename X, typename Y>
Composition<X, Y>::~Composition()
{
delete cp;
}
template <typename X, typename Y>
Comp_base<X, Y>* Composition<X, Y>::clone() const
{
return cp->clone();
}
template <typename X, typename Y>
Composition<X, Y>::Composition(const Composition& c):cp(c.clone()) { }
template <typename X, typename Y>
Composition<X, Y>& Composition<X, Y>::operator=(const Composition& c)
{
if(this != &c) {
delete cp; //!!!
cp = c.clone();
}
return *this;
}
template <typename X, typename Y>
Y Composition<X, Y>::operator()(X n) const
{
return cp->operator()(n);
}
任务完成!
关于Composition<int, int> fg(f, g); 这句话到底做了些什么呢?
<int, int>这个给出了类型形参X,Y
然后因为构造函数是模板,所以我们可以根据 f、g 的实际类型推断出类型T、G。因此我们不知可以组合函数,更可以组合函数对象了。