vps能同时做网站同时做其它事吗,宜春建设局网站,微平台推广是什么,如何建立一个免费的网站文章目录 一、类模板 - 函数声明与函数实现分离1、类模板 外部 实现 构造函数2、类模板 外部 实现 普通函数3、类模板 外部 实现 友元函数( 1 ) 错误示例及分析 - 类模板 的 外部友元函数 二次编译 问题( 2 ) 正确写法 二、代码示例 - 函数声明与函数实现分离1、代码示例2、执行… 文章目录 一、类模板 - 函数声明与函数实现分离1、类模板 外部 实现 构造函数2、类模板 外部 实现 普通函数3、类模板 外部 实现 友元函数( 1 ) 错误示例及分析 - 类模板 的 外部友元函数 二次编译 问题( 2 ) 正确写法 二、代码示例 - 函数声明与函数实现分离1、代码示例2、执行结果 将 类模板 函数声明 与 函数实现 分开进行编码 , 有 三种 方式 :
类模板 的 函数声明 与 函数实现 都写在同一个类中 , 也就是没有分开进行编码 ;类模板 的 函数实现 在 类外部进行 , 函数声明 和 实现 写在相同的 .cpp 源码文件中 ;类模板 的 函数实现 在 类外部进行 , 函数声明 和 实现 写在不同的 .h 和 .cpp 源码文件中 ;
上一篇博客 【C】泛型编程 ⑨ ( 类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中 | 类模板 的 外部友元函数问题 ) 实现了第一种情况 , 类模板 的 函数声明 与 函数实现 都写在同一个类中 , 也就是没有分开进行编码 ;
本篇博客 , 开始分析 第二种情况 , 类模板 的 函数实现 在 类外部进行 , 写在相同的 .h 和 .cpp 源码文件中 ; 一、类模板 - 函数声明与函数实现分离 1、类模板 外部 实现 构造函数 原来的构造函数是 :
template typename T
class Student
{
public:Student(T x, T y){this-a x;this-b y;}
}如果将 构造函数 实现 , 写在类外部的 .cpp 源码中 ,
首先 , 需要 声明 模板类型 , template typename T ;然后 , 通过 域操作符 访问 构造函数 , 并实现该函数 , 使用域操作符 时 , 前面的类 需要指定 具体的泛型类型 , 这里使用 声明的 T 模板类型 作为 具体的 泛型类型 ;
template typename T
StudentT::Student(T x, T y)
{this-a x;this-b y;
}在 类模板 内部 , 只需要声明该 构造函数 :
template typename T
class Student
{
public:Student(T x, T y);
}2、类模板 外部 实现 普通函数 将 类内部的 普通函数 实现 加法运算符重载 的函数 , 提取到 类模板 外部进行定义 ;
该函数的 返回值 和 参数 都涉及到 类模板 类型 ;
template typename T
class Student
{
public:// 重载 运算符Student operator(Student s){Student student(this-a s.a, this-b s.b);return student;}
}在类外部 实现 该 加号运算符重载 需要注意以下几点 :
首先 , 需要 声明 模板类型 , template typename T ;然后 , 通过 域操作符 访问 构造函数 , StudentT:: 后面跟上要访问的成员 ;最后 , 返回值和参数类型 , 如果是 类模板类型 Student , 需要在后面使用尖括号 指明具体的类型 , 这里具体的类型就是泛型 T ;
函数内部 Student 类型 , 可以加 T 也可不加 T , 不加 T 也可以使用 , 加了也不会报错 ;
// 重载 运算符
// 使用 StudentT:: 域操作符访问函数
template typename T
StudentT StudentT::operator(StudentT s)
{// 函数内部的类的 T 模板类型 , 可加 T 可不加 T // 不加 T 也可以使用 , 加了也不会报错Student student(this-a s.a, this-b s.b);return student;
}类模板内部 , 需要声明该 重载函数 ;
template typename T
class Student
{
public:// 重载 运算符Student operator(Student s);
}3、类模板 外部 实现 友元函数 友元函数 不是 类中的函数 , 是 类外部的函数 , 友元函数 中又用到了 泛型 T , 说明这是一个 模板函数 ;
友元函数 是 全局函数 , 不属于 类模板 , 不要使用 域操作符 访问友元函数 ;
友元函数 中的 泛型类型 , 要当做 函数模板 对待 ;
模板函数就涉及到 二次编译 问题 , 下面先分析一下 模板函数 二次编译 导致的 类模板的友元函数 问题 ;
友元函数 不要乱用 , 只有在 重载 左移 右移 操作符时 , 才使用 友元函数 ; ( 1 ) 错误示例及分析 - 类模板 的 外部友元函数 二次编译 问题 在 类模板 内部声明 友元函数 ,
template typename T
class Student
{// 左移运算符重载friend ostream operator(ostream out, Student s);
}在 类外部 实现 友元函数 ,
// Student 类的友元函数
// 左移运算符重载 函数
template typename T
ostream operator(ostream out, StudentT s)
{out a: s.a b: s.b endl;return out;
}运行时会报如下错误 :
已启动生成…
1------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1Test.obj : error LNK2019: 无法解析的外部符号 class std::basic_ostreamchar,struct std::char_traitschar __cdecl operator(class std::basic_ostreamchar,struct std::char_traitschar ,class Studentint ) (??6YAAAV?$basic_ostreamDU?$char_traitsDstdstdAAV01AAV?$StudentHZ)函数 _main 中引用了该符号
1D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Debug\HelloWorld.exe : fatal error LNK1120: 1 个无法解析的外部命令
1已完成生成项目“HelloWorld.vcxproj”的操作 - 失败。生成: 成功 0 个失败 1 个最新 0 个跳过 0 个 造成上述错误的原因 就是 函数模板 的实现机制 中的 二次编译 有关 ,
第一次编译 函数模板 时 , 只进行 简单的 语法分析 , 词法分析 , 生成一个函数头 ;第二次编译 函数模板 时 , 又生成一个 函数头 ;
这两次编译生成的 函数头 不一致 , 导致 无法找到 相应的 函数实现 ; ( 2 ) 正确写法 友元函数 不要乱用 , 只有在 重载 左移 右移 操作符时 , 才使用 友元函数 ; 这是 函数模板 二次编译 问题 ,
一般情况下 , 函数模板 只有在 调用时 , 才需要将 泛型类型 指明 , 在 函数名称后面 , 使用 注明泛型类型 ,
但是在 类模板 声明 友元函数 时 , 就需要指定 泛型类型 ;
这样才能将 类模板中的 泛型 T , 与 友元函数在 外部实现时 声明的 template typename T 关联起来 ; 在 类模板 内部声明 友元函数时 , 在函数名 operator 后面 加上 T ;
template typename T
class Student
{// 左移运算符重载friend ostream operator T (ostream out, Student s);
}在 类外部 实现 友元函数 保持不变 ;
// Student 类的友元函数
// 左移运算符重载 函数
template typename T
ostream operator(ostream out, StudentT s)
{out a: s.a b: s.b endl;return out;
}二、代码示例 - 函数声明与函数实现分离 1、代码示例 #include iostream
using namespace std; template typename T
class Student
{// 左移运算符重载friend ostream operator T (ostream out, Student s);public:// 构造函数Student(T x, T y);// 重载 运算符Student operator(Student s);public:T a, b;
};// 类模板构造函数
// 使用 StudentT:: 域操作符访问函数
template typename T
StudentT::Student(T x, T y)
{this-a x;this-b y;
}// 重载 运算符
// 使用 StudentT:: 域操作符访问函数
template typename T
StudentT StudentT::operator(StudentT s)
{// 函数内部的类的 T 模板类型 , 可加 StudentT 可不加 Student// 不加 T 也可以使用 , 加了也不会报错Student student(this-a s.a, this-b s.b);return student;
}// Student 类的友元函数
// 左移运算符重载 函数
template typename T
ostream operator(ostream out, StudentT s)
{out a: s.a b: s.b endl;return out;
}int main() {// 模板类不能直接定义变量// 需要将 模板类 具体化之后才能定义变量Studentint s(666, 888);cout s endl;Studentint s2(222, 111);cout s2 endl;// 验证 加法运算符 重载Studentint s3 s s2;// 验证 左移运算符 重载cout s3 endl;// 控制台暂停 , 按任意键继续向后执行system(pause);return 0;
}2、执行结果 执行结果 :
a:666 b: 888a:222 b: 111a:888 b: 999Press any key to continue . . .