内联函数
内联即inline,首先想到的是内联函数,引入内联函数的目的是为了解决程序中函数调用的效率问题。
内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质。编译时,类似宏替换,使用函数体替换调用处的函数名。
一般在代码中用inline修饰,但能否形成内联函数,需要看编译器对该函数定义的具体处理。
举个例子:
inline int add(int x, int y, int z)
{
return x + y + z;
}
在程序中,调用其函数时,该函数在编译时被替代,而不像一般函数那样实在运行时被调用。
可以看到,类模板和函数模板的创建过程几乎没有什么区别。
“把相关代码放在一起”这条重要规则同样适用于类模板。
不管是什么模板,编译器都必须看到全部的代码才能为一种给定的类型创建出一个新的实现来。
在创建类模板时,避免类声明和类定义相分离的一个好办法是使用内联方法。
在类里,内联方法的基本含义是在声明该方法的同时还对它进行定义。
例子:
class Person
{
Person(std::string name)
{
this-> name = name;
}
//....
}
除了可以更好的帮助编译器处理类模板之外,使用内联方法还有一个很好的作用:可以让你少打些字并让源代码的可读性变得更好。
下面就改善一下上一节课的栈程序:
#include <iostream>
#include <string>
template <class T>
class Stack
{
public:
Stack(unsigned int size = 100)
{
this->size = size;
data = new T[size];
sp = 0;
}
~Stack()
{
delete[] data;
}
void push(T value)
{
data[sp++] = value;
}
T pop()
{
return data[--sp];
}
private:
unsigned int size;
unsigned int sp;
T *data;
};
int main()
{
Stack<int> intStack(100);
intStack.push(1);
intStack.push(2);
intStack.push(3);
std::cout << intStack.pop() << std::endl;
std::cout << intStack.pop() << std::endl;
std::cout << intStack.pop() << std::endl;
return 0;
}
注意:
如果你打算在自己的程序里使用Stack模板,一定要给它增加一个副本构造器和一个赋值操作符重载,编译器就会出错(参考动态内存那里的内容。)
我们刚刚的代码还缺少必要的错误处理功能,例如在栈已满的时候调用push()方法,或者在栈为空的时候调用pop()方法,会导致程序运行出错。
我们应该设法让栈在遇到这两种情况的时候抛出一个异常来处理。
C++并没有限制只能使用一个类型占位符,如果类模板需要一种以上的类型,根据具体情况多使用几个占位符即可。
templata <class T, class U>
class Myclass
{
// ... ...
}
在实例化时,我们只需要这么做:
MyClass <int, float> myClass;