威尼斯人源码下载

威尼斯人源码下载http://hubawl.com/thread-321-1-1.html

威尼斯人源码下载

普通类函数的定义不能写在头文件中,因为你和类模板不一样,类模板虽然定义了但不生成具体函数,主函数所在的.cpp文件包含这个头文件,会把头文件中的代码都写入到主.cpp中
//普通类的函数就会在头文件和主.cpp文件中定义两次,而类模板在头文件中并不生成具体函数,只在主.cpp文件中生成了具体函数,因此只定义了一次
Animal1::Animal1(int age, string color)
{
this->age = age;
this->color = color;
}
*/

/
//普通函数和普通类函数一样
void print111()
{
cout << "111111" << endl;
}
/

template<class T1, class T2> class Animal2;
template<class T1, class T2> void printAnimal(Animal2<T1, T2> &a);
//模板类多文件形式声明定义
template<class T1, class T2>
class Animal2
{
public:
Animal2(T1 age, T2 color);
void show();
//左移操作符重载只可以写在类外面,不可以写在类内部操作符重载
//template<class T1, class T2>//这只在window下编译可以通过,但在linux下编译不通过,这是编译器的差异,用下面一种形式,两种平台都可以
//类模板的友元函数为函数模板,不是具体函数,因此在类模板中声明,也需要带上template<T>,但这种形式在linux不适用,因此换成下面一段代码的写法
friend ostream &operator<<<T1, T2>(ostream &out, Animal2<T1, T2> &a);

//普通友元函数,很复杂,因此不要滥用友元函数!!!
friend void printAnimal<T1, T2>(Animal2<T1, T2> &a);
private:
T1 age;
T2 color;
};

//因为没有具体类型,编译时没有办法生成具体函数的
//只有有具体调用的时候,传进来类型时,函数模板才会生成具体函数
//一定要带上类模板声明,且每个函数都要写一遍类模板声明
template<class T1, class T2>
Animal2<T1, T2>::Animal2(T1 age, T2 color)
{
this->age = age;
this->color = color;
}

template<class T1, class T2>
void Animal2<T1, T2>::show()//也一定要带,不论什么原因
{
cout << "age is " << age << endl;
cout << "color is " << color << endl;
}

//Animal2类的友元函数,这也不是具体函数,只要有模板T的都不为具体函数,这本质为函数模板,友元函数模板,因此可以写在头文件中,主.cpp文件调用是不会发生重复定义,因为这边生成的不是具体函数,而主.cpp那边传入具体类型参数,在主.cpp那边才变成具体函数
template<class T1, class T2>
ostream &operator<<(ostream &out, Animal2<T1, T2> &a)
{
out << "age is " << a.age << endl;
out << "color is " << a.color << endl;
return out;
}

template<class T1, class T2>
void printAnimal(Animal2<T1, T2> &a)
{
cout << "age is " << a.age << endl;
cout << "color is " << a.color << endl;
}

//类模板的多态,与我的猜想完全一样
template<class T>
class Parent
{
public:
Parent()
{
age = 1;
}
virtual void show()
{
cout << "1111111111111111111111" << endl;
}
virtual ~Parent()
{

}
private:
T age;
};

//子类继承了父类,父类是模板类,当子类实例化时,首先创建的是父类对象,因此需要给父类指定类型
//类模板派生普通类
class Child1 :public Parent<int>
{
public:
virtual void show()
{
cout << "222222222222222222222222" << endl;
}
private:

};

//类模板派生类模板
template<class T>
class Child2 :public Parent<T>//这儿的T为子类的类型参数,父类的对象需要指定类型,即用子类的类型参数代替,在构建子类对象的时候,指定T的类型也就指定了父类成员变量的类型
{
public:
virtual void show()
{
cout << "3333333333333333333333333" << endl;
}
private:

};

//类模板的多态实现
//这个形式也验证了只有有类型模板的,都要带template<class T>模板声明,这个函数本质是不是具体函数,只是函数模板,只有当传进参数类型时,才变为具体函数,因此需要写在头文件中,反而不能写在实现的.cpp文件中,但不包含主.cpp文件
template<class T>
void funcParent(Parent<T> *p)
{
p->show();
}

//类模板中含有静态成员变量,根据传进来的类型创建具体类(这时才会创建具体静态成员变量),因此静态成员变量根据传入不同的类型,而归于与不同的类,即传入类型相同的对象共同持有一个静态成员变量,另外相同的共同持有一个静态成员变量
template<class T>
class Building
{
public:
T getA();
private:
static int a;
};
//类外初始化
//这是类模板的静态成员变量初始化,但类模板并不是具体的类,因此只有当具体的类被确定时,这个静态成员变量才被确实,类模板是不包含具体的静态成员变量的,类模板生成的具体类才拥有静态成员变量
template<class T>
int Building<T>::a = 96;

template<class T>
T Building<T>::getA()
{
a++;
return a;
}

Animal.cpp
#include "Animal.h"

Animal1::Animal1(int age, string color)
{
this->age = age;
this->color = color;
}

void Animal1::show()
{
cout << "color is " << color << endl;
cout << "age is " << age << endl;
}

Animal.hpp
//一般类模板的声明和实现都写在一个文件中,我们把这种文件命名为.hpp
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>

template<class T1, class T2>
class Animal3
{
public:
Animal3(T1 age, T2 color);
void show();
private:
T1 age;
T2 color;
};

//类模板参数在三处地方用到
//1.子类继承父类的时候,例:class Child :public Parent<int, string>
//2.实现类模板里的函数模板,例:Animal<T1, T2>::Animal(T age){}
//3.构造类模板对象,例:Animal<int, string> a(10)
//4.操作符重载友元函数模板
//类中声明:friend ostream &operator<<<T1, T2>(ostream &out, Animal2<T1, T2> &a)
//类外实现:(这儿一定有模板声明:template<class T1, class T2>)ostream &operator(ostream &out, Animal2<T1, T2> &a){}
//5.普通友元函数模板
//类外声明:template<class T1, class T2> class Animal2; template<class T1, class T2> void printAnimal(Animal2<T1, T2> &a);//普通友元函数模板一定需要类外声明,且是模板形式的声明
//类内声明:friend void printAnimal<T1, T2>(Animal2<T1, T2> &a)
//类外实现:(这儿一定有模板声明:template<class T1, class T2>) void printAnimal(Animal2(T1, T2) &a){}
//6.类模板返回类对象本身,此时函数返回值类型需要写成,例:MyArray<T> void getArray(){}

//函数模板类型可以自动推导,不需要指定
template<class T1, class T2>
Animal3<T1, T2>::Animal3(T1 age, T2 color)
{
this->age = age;
this-> color = color;
}

template<class T1, class T2>
void Animal3<T1, T2>::show()
{
cout << "age is " << age << endl;
cout << "color is " << color << endl;
}

c++模板类详解.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "Animal.h"

//解决模板类.h文件和.cpp文件分开编写出现的无法解析的外部符号问题
//把.cpp文件包含进来,即把.cpp文件的内容都拷贝到这个.cpp文件中,那么编译主函数.cpp文件时,就不需要生成函数符号,最后再链接了,直接生成具体的函数了
//主函数所在的.cpp文件中,如果包含普通类的实现.cpp文件,会报重复定义错误,因为普通类的.cpp文件实现了一次类的定义,主函数所在.cpp文件也实现了一次类的定义,因为include是编译器把代码拷贝到此文件中,因此重复定义了,包含头文件也是把头文件的代码写在主函数所在的.cpp文件中,但那只是声明,并没有重复定义
//#include "Animal.cpp"

//一般把类模板的声明和实现写在一个文件中,这个文件为.hpp文件
#include "Animal.hpp"
using namespace std;

class Teacher
{
public:
Teacher(int age);
private:
int age;
};
Teacher::Teacher(int age)//普通函数也需要加作用域
{
this->age = age;
}

//类模板中有多个类型参数的用法
template<class T1, class T2>
class Student
{
public:
Student(T1 name, T2 age)
{
this->age = age;
this->name = name;
}
private:
T1 name;
T2 age;
};

int main()
{
//普通类继承模板类,实现父类的成员变量要和子类赋予父类的一致
Parent<int> p1 = new Child1;
//类模板继承类模板,
Parent<string>
p2 = new Child2<string>;
funcParent(p1);
funcParent(p2);

Student<string, int> s("xuhaoxuan", 10);//多个类型参数的对象是这样创建的

Animal1 a1(10, "yellow");

//c++编译机制
//c++编译是独立编译的,即每个文件独立编译一次,生成一个.o文件,再把生成的.o文件链接在一起
//在编译一个.cpp文件时,发现一个函数调用,但在当前文件找不到这个函数的实现,则在函数位置生成一个符号,如果调用函数有错误,则在链接阶段报错
Animal2<int, string> a2(5, "yellow");
cout << a2;
printAnimal(a2);

Animal3<int, string> a3(10, "green");

Building<int> b1, b2, b3;
Building<char>b4, b5, b6;
cout << "b1.a = " << b1.getA() << endl;
cout << "b2.a = " << b2.getA() << endl;
cout << "b3.a = " << b3.getA() << endl;
cout << "b4.a = " << b4.getA() << endl;
cout << "b5.a = " << b5.getA() << endl;
cout << "b6.a = " << b6.getA() << endl;
return 0;
}

猜你喜欢

转载自blog.51cto.com/13855861/2137158
今日推荐