class与struct 区别
从struct关键字在C和C++中的区别说开去。在C的编译器中,代码
struct label
{
/*stuff*/
};
只是定义了一个结构体标签label。要想在代码中产生这个结构体的具体实现t,必须采用
struct label t;
这就是为什么在C程序中常常用typedef来定义一个struct的原因了。但是上面的语句在C++的编译器中都是可行的:换而言之,C++中的struct关键字能定义一个结构体,而C中的struct关键字只能定义一个结构体的标签。
在C++中struct得到了很大的扩充:
1.struct可以包括成员函数
2.struct可以实现继承
3.struct可以实现多态
在C++中探讨class和struct关键字的不同
- struct中默认的存取权限是public,而class中则是private;
- 当用struct关键字构建的类成为父类时,默认的继承权限为public;而当用class关键字构建的类成为父类时,默认的继承权限是private;
- 关于使用大括号初始化,class和struct如果定义了构造函数的话,都不能用大括号进行初始化,如果没有定义构造函数,struct可以用大括号初始化。如果没有定义构造函数,且所有成员变量全是public的话,可以用大括号初始化。
- 在模板template的<>中的类型定义仅仅支持class和typename,并不支持struct。
为什么template不支持struct?前面说了,C++中保留struct仅仅是为了与C的兼容性的话,而模板设计的初衷就没有想过与C兼容,所以抛弃struct关键字也是很自然的事情了。 - 内存布局的不一致。在C语言的时代,一些程序员常常将单一元素的数组放到一个struct的尾部,于是每个struct object就可以拥有可变大小的数组了,也即柔性数组(flexible array),C99
中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组。sizeof
返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用malloc
()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
example:
#include <cstdio>
#include <cstdlib>
#include <cstring>
struct mumble
{
/*stuff*/
char pc[];
};
int main()
{
char s[] = "I'm a struct tip!";
struct mumble *pmumble = (structmumble*)malloc(sizeof(struct mumble)+strlen(s));
strcpy(pmumble->pc,s);
printf("%s",pmumble->pc);
printf("%d",sizeof(pmumble->pc));
return 0;
}
C++中的模板
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。
模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。
每个容器都有一个单一的定义,比如 向量,我们可以定义许多不同类型的向量,
比如 vector 或 vector
1.函数模板
template <class type> ret-type func-name(parameter list)
{
// 函数的主体
}
type 是函数所使用的数据类型的占位符名称。这个名称可以在函数定义中使用
示例:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
inline T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}
int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
2.类模板
泛型类声明的一般形式如下所示
template <class type> class class-name {
.
.
.
}
type 是占位符类型名称,可以在类被实例化的时候进行指定。您可以使用一个逗号分隔的列表来定义多个泛型数据类型。
下面的实例定义了类 Stack<>,并实现了泛型方法来对元素进行入栈出栈操作:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
using namespace std;
template <class T>
class Stack {
private:
vector<T> elems; // 元素
public:
void push(T const&); // 入栈
void pop(); // 出栈
T top() const; // 返回栈顶元素
bool empty() const{ // 如果为空则返回真。
return elems.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem)
{
// 追加传入元素的副本
elems.push_back(elem);
}
template <class T>
void Stack<T>::pop ()
{
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
// 删除最后一个元素
elems.pop_back();
}
template <class T>
T Stack<T>::top () const
{
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
// 返回最后一个元素的副本
return elems.back();
}
int main()
{
try {
Stack<int> intStack; // int 类型的栈
Stack<string> stringStack; // string 类型的栈
// 操作 int 类型的栈
intStack.push(7);
cout << intStack.top() <<endl;
// 操作 string 类型的栈
stringStack.push("hello");
cout << stringStack.top() << std::endl;
stringStack.pop();
stringStack.pop();
}
catch (exception const& ex) {
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}
结果:
7
hello
Exception: Stack<>::pop(): empty stack
类模板和模板类区别
类模板,实际上是建立一个通用类,其数据成员、成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从而实现了不同类的功能。
-
template:是一个声明模板的关键字,它表明声明一个模板
-
类型参数:通常用C++标识符表示,如T、Type等,实际上是一个虚拟的类型名,现在未指定它是哪一种具体的类型,但使用类模板时,必须将类型参数实例化。
-
typename和class的作用相同,都是表示其后面的参数是一个虚拟的类名(即类型参数).
#include<iostream.h>
template<typename T> //模板声明,其中T为类型参数
class Compare{
public:
Compare(T i,T j)
{
x = i;
y = j;
}
T max();
private:
T x,y;
};
template<class T>
T Compare<T>::max()
{
return (x>y)?x:y;
}
int main()
{
Compare<int>com1(3,7); //用类模板定义对象com1,此时T被int替代
Compare<double>com2(12.34,56.78); //用类模板定义对象com2,此时T被double替代
Compare<char>com3('a','x'); //用类模板定义对象com3,此时T被char替代
cout<<"其中的最大值是:"<<com1.max()<<endl;
cout<<"其中的最大值是:"<<com2.max()<<endl;
cout<<"其中的最大值是:"<<com3.max()<<endl;
return 0;
}
此例中,类模板Compare经实例化后生成了3个类型分别为int、double、char的模板类,这3个模板类
经实例化后又生成了3个对象com1、com2、com3。类模板代表了一类类,模板类表示某一具体的类。
类模板 Compare<T>
实例化成模板类:Compare<int> Compare<double> Compare<char>
实例化模板类对象:com1 com2 com3