c++沉思录笔记(21章代码)隐藏中间类型

上次我们已经可以复合(组合)函数了,我们可以写出下面的代码

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。因此我们不知可以组合函数,更可以组合函数对象了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值