C++03模板,const,静态成员方法,模板实现栈

1.模板

模板的意义:可以对类型进行参数化

函数模板

怎么定义模板参数列表
模板类型参数
模板非类型参数
函数模板
模板的实例化
模板函数 ===》 需要编译的
模板的实参推演 compare<char*>(“aaa”, “bbb”)
模板的特例化(特化,专用化)
非模板函数,函数模板的特例化,函数模板的共存关系(重载关系)

template<typename T>
class Link
{
public:
	Link(){ mphead = new Node(); }
	~Link();
	void insertHead(const T &val);
	bool query(const T &val)
	{
		Node *pcur = mphead->mpnext;
		while (pcur != NULL)
		{
			if (pcur->mdata == val)
				return true;
			pcur = pcur->mpnext;
		}
		return false;
	}
private:
	struct Node
	{
		// 零构造  零初始化
		Node(T data=T()) :mdata(data), mpnext(NULL){}

		T mdata;
		Node *mpnext;
	};
	// 返回第一个值为val节点的节点地址
	Node* getNodeAddr(const T &val);
	Node *mphead;
};

template<typename T>
Link<T>::~Link()
{
	Node *pcur = mphead;
	while (pcur != NULL)
	{
		mphead = mphead->mpnext;
		delete pcur;
		pcur = mphead;
	}
}
template<typename T>
void Link<T>::insertHead(const T &val)
{
	Node *pnode = new Node(val);
	pnode->mpnext = mphead->mpnext;
	mphead->mpnext = pnode;
}
//Link<T>::Node依赖名称不是类型
template<typename T>
typename Link<T>::Node* Link<T>::getNodeAddr(const T &val)
{
	Node *pcur = mphead->mpnext;
	while (pcur != NULL)
	{
		if (pcur->mdata == val)
			return true;
		pcur = pcur->mpnext;
	}
	return false;
}
int main()
{
	//int a = int();
	//cout << a << endl;
	//类模板的选择性实例化
	Link<char*> strLink1;
	strLink1.insertHead("aaa");
	strLink1.insertHead("bbb");
	strLink1.insertHead("ccc");

	cout << strLink1.query("bbb") << endl;

	char a[] = "aaa";
	char b[] = "bbb";
	char c[] = "ccc";
	Link<char*> strLink2;
	strLink2.insertHead(a);
	strLink2.insertHead(b);
	strLink2.insertHead(c);

	cout << strLink2.query("bbb") << endl;
	return 0;
}

两个问题点:
1.typename的另一层含义
2.成员方法的模板

1.1函数模板

模板参数列表    函数模板
template<typename T>
bool compare(T a, T b)
{
	cout << "template compare" << endl;
	cout << typeid(T).name() << endl;
	return a > b;
}  // const int a=10;  int b=20;
/*
模板函数
bool compare<int>(int a, int b)
{
	cout << "template compare" << endl;
	cout << typeid(int).name() << endl;
	return a > b;
}

1.2模板的特例化版本

template<>
bool compare<char*>(char * a, char *b)
{
	cout << "compare<char*>" << endl;
	return strcmp(a, b);
}
template<>
bool compare<int>(int a, int b)
{
	cout << "compare<int>" << endl;
	return a > b;
}
bool compare(char *a, char *b)
{
	cout << "compare_char*" << endl;
	return strcmp(a, b);
}
bool compare(int a, int b)
{
	cout << "compare_in>" << endl;
	return a > b;
}
template<typename T>  // 
void sort(T arr[], int size)
{
	T tmp;
	for (int i = 0; i < size - 1; ++i)
	{
		for (int j = 0; j < size - 1 - i; ++j)
		{
			if (arr[j] > arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
template<>  // 
void sort<char*>(char* arr[], int size)
{
	char* tmp;
	for (int i = 0; i < size - 1; ++i)
	{
		for (int j = 0; j < size - 1 - i; ++j)
		{
			if (strcmp(arr[j], arr[j + 1]) > 0)
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
int main(int argc, char* argv[])
{
	int arr[] = { 23, 4, 67, 8, 90, 21, 35, 74 };
	sort<int>(arr, sizeof(arr)/sizeof(arr[0]));
	for (int val : arr)
	{
		cout << val << " ";
	}
	cout << endl;
	char *arr1[] = { "aaa", "bbb", "ccc" };
	sort<char*>(arr1, sizeof(arr1) / sizeof(arr1[0]));
	for (char* ptr : arr1)
	{
		cout << ptr << " ";
	}
	cout << endl;
	// 函数的调用点 =》 根据指定类型函数模板进行实例化  =》 模板函数
	//compare<int>(10, 20);  
	//compare<double>(10.5, 20.5);

	//compare(20, 30);

	//char a[] = "aaa";
	//char b[] = "bbb";
	//compare(a, b);
	//compare<char*>(a, b);

	return 0;
}

2.问题(多态)

1.你怎么理解C++里面的多态?
静态的多态(编译时期的多态):函数重载, 模板
动态的多态(运行时期的多态):继承中的虚函数

2.能不能把函数模板和模板的调用写在两个不同的源文件当中?
模板本身不编译,实例化以后才编译,模板不编译 模板代码都写在头文件当中, 各个源文件直接include使用就可以

test.cpp   
template<typename T>
bool compare(T a, T b)
{
	return a>b;
}

main.cpp

template<typename T>
bool compare(T a, T b);

int main()
{
	compare(10, 20);
	return 0;
}

3.例子

// 在一个数组中,查找一个元素,找到返回元素的下标,找不到返回-1
template<typename T>
int findValue(T arr[], int size, const T &val)
{
	for (int i = 0; i < size; ++i)
	{
		if (arr[i] == val)
			return i;
	}
	return -1;
}
template<>
int findValue(char* arr[], int size, char* const &val)
{
	for (int i = 0; i < size; ++i)
	{
		if (strcmp(arr[i], val) == 0)
			return i;
	}
	return -1;
}
int main()
{
	char a[] = "aaa";
	char b[] = "bbb";
	compare<char*>(a, b);

	char *arr[] = {"aaa", "bbb", "ccc"};
	int index = findValue<char*>(arr, 3, "bbb");
	cout << "index:" << index << endl;

4.成员方法的分类

4.1分类

1.普通的成员方法
。属于类的作用域
。调用必须依赖对象
。可以任意访问自己其它private私有成员

2.static成员方法 => 访问其它的静态成员
。属于类的作用域
。调用必须依赖类的作用域
。可以任意访问自己其它private静态私有成员

3.const常成员方法
。属于类的作用域
。调用必须依赖对象
。可以任意访问自己其它private私有成员,但是只能读,而不能写

4.2用法

常对象 =》 只能调用 =》 常成员方法
// 常识:普通方法只有读操作,都实现成const常方法;如果有写操作,那么
// 实现成普通方法
// 静态成员方法和普通成员方法有什么区别?
static void showBookCount() // 没有this指针
{
cout << “Book Count:” << mCount << endl;
}

onst int BOOK_LEN = 20;
class CBook
{
public:
	CBook(char *n, int a, double p)
		:mAmount(a), mPrice(p)
	{
		strcpy(mName, n);
		mCount++;
	}
	/*void showBookBasicInfo() // CBook *this 编译自动添加this指针形参
	{
		cout << "name:" << this->mName << " amount:" << this->mAmount <<
			" price:" << this->mPrice << endl;
	}*/
	// 常对象 =》 只能调用 =》 常成员方法
	// 常识:普通方法只有读操作,都实现成const常方法;如果有写操作,那么
	// 实现成普通方法
	void showBookBasicInfo() const// const CBook *this
	{
		cout << "name:" << this->mName << " amount:" << this->mAmount <<
			" price:" << this->mPrice << endl;
	}
	// 静态成员方法和普通成员方法有什么区别?
	static void showBookCount() // 没有this指针
	{
		cout << "Book Count:" << mCount << endl;
	}
private:
	char mName[BOOK_LEN];
	int mAmount;
	double mPrice;
	static int mCount;  // 静态成员变量的声明
};
// 类的静态成员变量必须在类外进行初始化
int CBook::mCount = 0;

int main(int argc, char* argv[])
{
	CBook book1("天龙八部", 10, 80.0);
	CBook book2("倚天屠龙记", 20, 70.0);
	CBook book3("射雕英雄传", 30, 90.0);
	CBook book4("雪山飞狐", 30, 90.0);

	book1.showBookBasicInfo();  // CBook*
	CBook::showBookCount();

	const CBook book5("圣经", 30, 90.0);
	// CBook::showBookBasicInfo(&book5)    const CBook*
	book5.showBookBasicInfo(); // 常对象调用普通方法???  不能!!!

	return 0;
}

5.用模板实现栈

template<typename T>
class SeqStack // 模板名称 SeqStack<T> 必须指定实例化模板的类型
{
public:
	SeqStack(int size = 10)
	{
		mTop = 0;
		mSize = size;
		mpStack = new T[mSize];
	}

	~SeqStack()
	{
		delete[]mpStack;
	}

	SeqStack<T>(const SeqStack<T> &src)
	{
		mTop = src.top;
		mSize = src.mSize;
		mpStack = new T[mSize];
		for (int i = 0; i < mTop; i++)
		{
			mpStack[i] = src.mpStack[i];
		}
	}

	SeqStack<T>& operator=(const SeqStack<T> &src)
	{
		if (this == &src)
		{
			return *this;
		}

		delete []mpStack;

		mTop = src.top;
		mSize = src.mSize;
		mpStack = new T [mSize];
		for (int i = 0; i < mTop; i++)
		{
			mpStack[i] = src.mpStack[i];
		}

		return *this;
	}

	void push(const T &val)
	{
		if (full())
		{
			T *ptmp = new T [mSize *2];
			for (int i = 0; i < mTop; i++)
			{
				ptmp[i] = mpStack[i];
			}
			delete []mpStack;
			mpStack = ptmp;
			mSize *= 2;
		}
		mpStack[mTop++] = val;
	}

	void pop();

	T top()const
	{
		return mpStack[top - 1];
	}

	bool full()const
	{
		return mTop == mSize;
	}

	bool empty()const
	{
		return mTop == 0;
	}
private:
	T *mpStack;
	int mTop;
	int mSize;
};

template<typename T>
void SeqStack<T>::pop()
{
	if (empty())
	{
		return;
	}
	--top;
}

int main()
{
	SeqStack<int> stack1;
	SeqStack<double> stack2;
	SeqStack<MazeNode> stack3;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值