20170305STL01_泛型编程/模版

泛型编程:

1:STL目前在国内的资料比较少,国外相对较多。STL用得好的话,一个人的效率相当于十个人。
    1:编程就是生产一个工具,这个工具他能够帮人们做很多重复的事情!
    2:编程过程中,我们需要进行设计,分析,更新,维护。我们需要考虑的是这个软件的架构,代码量等。
    3:编码量将决定我们需要多少人来工作,所以当时Java很流行,生产力大。C++也推出了模版编程。
    4:模版它是一个能够产生代码的代码。这也是模版的意义。他改变了很多设计方式。
    5:他从设计角度帮我们解决很多问题。
2:牲口圈舍的设计:

        按C语言的思维(这个图是C++,但思想是C思想),如果再加一只羊,我们就得加两个模块(羊和羊圈),他们都是强聚合关系,最后将非常难以管理。

        按方案二:将所有动物抽象成一个父类,这样接口很简单,谁进去,就变成什么棚,适合哪种动物。这就是多态的机制实现的自动匹配。但是,这样和现实是脱节的,不可能有这样一个东西,虽然代码量小,但是难以让人理解。

        根据方案三:泛型编程(自动推导式编程),他抽象出来的是实际有的。相当于一个产生器,会产生实实在在存在的代码。

编程的思想:

1:泛型编程,面相对对象,使用对象,他和我们语言的本身是没有关系的,他们都是一种思想、是一种哲学。
2:上面的例子就是三种思想:过程、对象、泛型。三种思想最终的目的都是写出好的程序,他们本身是没有好坏之分的。

类模版基础使用:

1:之前我们自己写的Array类只能保存一种类型的数据,但是STL里面的却可以保存任何类型的。我们可以使用模版的方式来实现。
2:template<typename T>;。typename后面跟的是一个“类型变量”,之后传什么类型,这个T就代表什么类型。
3:template<class T>;。template后面只可能跟这两个关键字,他们的作用都是一样的。但是class使用得比较少,已被废弃,但编译器还可以使用。
4:测试代码:
#ifndef ARRAY_H_
#define ARRAY_H_

template<typename T>//已经开始在做泛型了。
class Array
{
public:
explicit Array(const size_t size = 10);
~Array();
explicit Array(const Array& other);
Array& operator=(Array&other);
const T& operator[](const size_t index) const;
T& operator[](const size_t index);
void Append(const T value);
private:
T *data_;
size_t size_;
unsigned int pos_;

};
//--------------------------------------函数实现-----
template<typename T>
void Array<T>::Append(const T value)
{
data_[pos_++] = value;
}

template<typename T>
T& Array<T>::operator[](const size_t index)
{
return data_[index];
}

template<typename T>
const T& Array<T>::operator[](const size_t index) const
{
return data_[index];
}

template<typename T>
Array<T>& Array<T>::operator=(Array<T>&other)
{
if (&other == this)
return *this;
delete[]data_;
size_ = other.size_;
data_ = new int[size_];
memcpy(data_, other.data_, size_*sizeof(T));
return *this;
}

template<typename T>
Array<T>::Array(const Array<T>& other)
{
data_ = new T[other.size_];
size_ = other.size_;
memcpy(data_, other.data_, size_*sizeof(T));
}

template<typename T>
Array<T>::~Array()
{
delete[]data_;
}

template<typename T>
Array<T>::Array(const size_t size /*= 10*/)
{
data_ = new T[size_];
}

#endif//!ARRAY_H_

//main.c类容:
#include <iostream>
#include "Array.h"
int main()
{
//	int ar[10] = { 0 };
Array<int> a(10);
//Array只是一个int型的Array。如果要保存double类型的数据,就又得做一个保存double的类。
//这时候就可以用泛型的方式来解决。
a.Append(1);
a.Append(2);
a.Append(3);
a.Append(4);
a.Append(5);
//宏是编译时替换,而模版是编译时生成。编译器在编译的时候会copy生成多个类,它对应你是用过的类型。
Array<char> c;
c.Append('a');
c.Append('b');
c.Append('c');
c.Append('d');
c.Append('e');
std::cout << a[3] << std::endl;
std::cout << c[3] << std::endl;
return 0;
}

类外部模版类的类名:

使用模版后,class的类型已经发生了改变的,应该在类名后面加上<T>.

函数模版:

在类里面使用的模版成为类模版,这个类称为模版类。

#include <iostream>

template<typename T, typename T2>
class Demo
{
public:
	Demo(T2 in)
	{

	}
private:
	T tdemo;
	T2 t2Demo;
};

template<typename T, int size>//模版参数,可以直接拿来使用,但必须是常量。
class Demo3
{
public:
	Demo3(T in)
	{
		size_ = size;
	}
private:
	int size_;
	T tdemo;
};

int main()
{
	Demo <int, float> demo(float(1.003));

	return 0;
}

1:模版还可以和函数相结合使用,最著名的就是Swap交换函数。它可以推导参数的类型,产生相应的代码。
2:你使用了多少类型,他就会生成多少个函数,而且每个函数的地址是不一样的。
3:如果我们使用的方式出错,他就会推到不出来,导致出错,这时候,我们可以强制指定类型。

4:模版函数是可以重载的。也可以特化(把将会生成的函数自己写一遍,实现特殊的效果)。

5:但凡使用了模版,就很可能存在重载,所以可能存在二义性的问题。而且在模版里面的重载是不可以进行提升转换的。

#include <iostream>

template<typename T, typename T2>
class Demo
{
public:
	Demo(T2 in)
	{

	}
private:
	T tdemo;
	T2 t2Demo;
};

template<typename T, int size>//模版参数,可以直接拿来使用,但必须是常量。
class Demo3
{
public:
	Demo3(T in)
	{
		size_ = size;
	}
private:
	int size_;
	T tdemo;
};

template<typename T>
void Swap(T&lhs, T&rhs)
{
	T temp = lhs;
	lhs = rhs;
	rhs = temp;
}
void Swap(int&lhs, double&rhs)//重载的
{

}
void Swap(int&lhs, int&rhs)//特化的(相当于一个特例,模版不再自己生成这个)
{

}
template<typename T1, typename T2>
void Swap(T1 lhs, T2 rhs)
{
	Swap<double>(lhs, rhs);
}
int main()
{
	Demo <int, float> demo(float(1.003));
	int a = 10, b = 20;
	Swap(a, b);
	std::cout << a << "  " << b << std::endl;
	int aa = 10;
	double bb = 20;
//	Swap(aa, bb);//这行代码会出错。
//	Swap<double>(aa, bb);//会强制生成double的版本。
	//error C2664: “void Swap<double>(T &,T &)”: 无法将参数 1 从“int”转换为“double &”
	Swap(aa, bb);//将会调用重载的函数。
	return 0;
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值