C++ (3)
这次我们来研究一下 类模板 和函数的重载
类模板
类模板 就是帮助我们更加方便的工具 再一些 类中重复工作 功能相同 但是就是数据类型不同 我们也不能在建立一个新的 类吧所以我们 选择 类模板
c++
//这是声明类型
template <class 参数类型名字>
//---------------------------------------------------------------
//示例
template <class line>
class lines
{
public:
lines(line a,line b) //构造函数的 方法
}
//这个类模板就是 相当于int char 不过都能兼容而已
下面是拓展
c++
/*在C++中,你不能直接“终止”一个类模板,因为模板本身不是运行时的实体,而是在编译时根据需要的类型进行实例化的。但是,你可以通过几种方式来限制或控制模板的实例化。
显式特化:你可以为特定的类型提供模板的特化版本。这允许你为某些类型定制模板的行为。当你尝试使用这些特定类型实例化模板时,编译器将使用特化版本而不是通用模板。*/
cpp
template <>
class MyClass<int> {
// 专门为int类型定制的类实现
};
/*偏特化:偏特化允许你为模板的某些特定类型组合提供特定的实现。这通常用于处理模板类中有多个类型参数的情况。*/
cpp
template <typename T>
class MyClass<T*> {
// 专门为指针类型定制的类实现
};
/*静态断言:你可以在模板类中使用static_assert来在编译时检查类型,如果不满足某些条件,则终止编译。这可以用来限制哪些类型可以被用来实例化模板。*/
cpp
template <typename T>
class MyClass {
static_assert(std::is_arithmetic<T>::value, "MyClass only supports arithmetic types.");
// 类的其他成员...
};
/*删除的函数模板:你可以声明一个删除的模板函数来阻止某些类型的实例化。例如,你可以声明一个构造函数或赋值操作符为删除状态,以防止不希望的类型被用于模板。*/
cpp
template <typename T>
class MyClass {
public:
MyClass() = default;
// 删除特定类型的构造函数,防止其实例化
template <typename U = T>
MyClass(typename std::enable_if<std::is_same<U, int>::value, U>::type* = 0) = delete;
// 类的其他成员...
};
/*SFINAE(Substitution Failure Is Not An Error):这是一种编译时技术,用于在模板实例化过程中排除不符合条件的函数或方法。通过使用std::enable_if等工具,你可以在编译时根据类型特征来选择性地启用或禁用特定的函数模板。
控制可访问性:通过将模板类的某些成员设为private或protected,并只在满足特定条件时通过public接口暴露它们,你可以控制哪些类型可以实例化模板。*/
这就是类模板
函数的重载
这个比较重要
c++
Box operator+(const Box&);//传递方式
Box operator+(const Box&,const Boxs&);//传递多个参数
正常情况下 + 这个符号无法运算 复数里面的变量的值所以通过 函数运算符重载的方式 进行赋值运算
c++
#include <iostream>
class Complex {
public:
Complex(double real = 0.0, double imag = 0.0) : real_(real), imag_(imag) {}
// 加法运算符重载
Complex operator+(const Complex& other) const {
return Complex(real_ + other.real_, imag_ + other.imag_);
}
// 减法运算符重载
Complex operator-(const Complex& other) const {
return Complex(real_ - other.real_, imag_ - other.imag_);
}
// 输出运算符重载,用于打印复数
friend std::ostream& operator<<(std::ostream& os, const Complex& complex) {
os << complex.real_ << (complex.imag_ < 0 ? " - " : " + ") << std::abs(complex.imag_) << "i";
return os;
}
private:
double real_;
double imag_;
};
int main() {
Complex c1(3.0, 2.0);
Complex c2(1.0, 7.0);
Complex sum = c1 + c2;
std::cout << "Sum: " << sum << std::endl; // 输出:Sum: 4.0 + 9.0i
Complex difference = c1 - c2;
std::cout << "Difference: " << difference << std::endl; // 输出:Difference: 2.0 - 5.0i
return 0;
} //示例
//一元运算
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 到无穷
int inches; // 0 到 12
public:
// 所需的构造函数
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
// 显示距离的方法
void displayDistance()
{
cout << "F: " << feet << " I:" << inches <<endl;
}
// 重载负运算符( - )
Distance operator- ()
{
feet = -feet;
inches = -inches;
return Distance(feet, inches);
}
};
int main()
{
Distance D1(11, 10), D2(-5, 11);
-D1; // 取相反数
D1.displayDistance(); // 距离 D1
-D2; // 取相反数
D2.displayDistance(); // 距离 D2
return 0;
}
//自增运算符
关系运算符
c++
//例如 >,<这种
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 到无穷
int inches; // 0 到 12
public:
// 所需的构造函数
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
// 显示距离的方法
void displayDistance()
{
cout << "F: " << feet << " I:" << inches <<endl;
}
// 重载负运算符( - )
Distance operator- ()
{
feet = -feet;
inches = -inches;
return Distance(feet, inches);
}
// 重载小于运算符( < )
bool operator <(const Distance& d)
{
if(feet < d.feet)
{
return true;
}
if(feet == d.feet && inches < d.inches)
{
return true;
}
return false;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11);
if( D1 < D2 )
{
cout << "D1 is less than D2 " << endl;
}
else
{
cout << "D2 is less than D1 " << endl;
}
return 0;
}
插入运算符重载(<<,>>)
c++
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 到无穷
int inches; // 0 到 12
public:
// 所需的构造函数
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
friend ostream &operator<<( ostream &output,
const Distance &D )
{
output << "F : " << D.feet << " I : " << D.inches;
return output;
}
friend istream &operator>>( istream &input, Distance &D )
{
input >> D.feet >> D.inches;
return input;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11), D3;
cout << "Enter the value of object : " << endl;
cin >> D3;
cout << "First Distance : " << D1 << endl;
cout << "Second Distance :" << D2 << endl;
cout << "Third Distance :" << D3 << endl;
return 0;
}
/*结果为
$./a.out
Enter the value of object :
70
10
First Distance : F : 11 I : 10
Second Distance :F : 5 I : 11
Third Distance :F : 70 I : 10
赋值运算符也可以
c++
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 到无穷
int inches; // 0 到 12
public:
// 所需的构造函数
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
void operator=(const Distance &D )
{
feet = D.feet;
inches = D.inches;
}
// 显示距离的方法
void displayDistance()
{
cout << "F: " << feet << " I:" << inches << endl;
}
};
int main()
{
Distance D1(11, 10), D2(5, 11);
cout << "First Distance : ";
D1.displayDistance();
cout << "Second Distance :";
D2.displayDistance();
// 使用赋值运算符
D1 = D2;
cout << "First Distance :";
D1.displayDistance();
return 0;
}
()这玩意也能重载
不说什么了上代码
c++
#include <iostream>
using namespace std;
class Distance
{
private:
int feet; // 0 到无穷
int inches; // 0 到 12
public:
// 所需的构造函数
Distance(){
feet = 0;
inches = 0;
}
Distance(int f, int i){
feet = f;
inches = i;
}
// 重载函数调用运算符
Distance operator()(int a, int b, int c)
{
Distance D;
// 进行随机计算
D.feet = a + c + 10;
D.inches = b + c + 100 ;
return D;
}
// 显示距离的方法
void displayDistance()
{
cout << "F: " << feet << " I:" << inches << endl;
}
};
int main()
{
Distance D1(11, 10), D2;
cout << "First Distance : ";
D1.displayDistance();
D2 = D1(10, 10, 10); // invoke operator()
cout << "Second Distance :";
D2.displayDistance();
return 0;
}
C++类成员访问运算符重载->
就是这个
逆天了
类成员访问运算符( -> )可以被重载,但它较为麻烦。它被定义用于为一个类赋予"指针"行为。运算符 -> 必须是一个成员函数。如果使用了 -> 运算符,返回类型必须是指针或者是类的对象。
运算符 -> 通常与指针引用运算符 * 结合使用,用于实现"智能指针"的功能。这些指针是行为与正常指针相似的对象,唯一不同的是,当您通过指针访问对象时,它们会执行其他的任务。比如,当指针销毁时,或者当指针指向另一个对象时,会自动删除对象。
间接引用运算符 -> 可被定义为一个一元后缀运算符。也就是说,给出一个类:
C++
class Ptr{
//...
X * operator->();
};
类 Ptr 的对象可用于访问类 X 的成员,使用方式与指针的用法十分相似。例如:
C++
void f(Ptr p )
{
p->m = 10 ; // (p.operator->())->m = 10
}
语句 p->m 被解释为 (p.operator->())->m。同样地,下面的实例演示了如何重载类成员访问运算符 ->
c++
#include <iostream>
#include <vector>
using namespace std;
// 假设一个实际的类
class Obj {
static int i, j;
public:
void f() const { cout << i++ << endl; }
void g() const { cout << j++ << endl; }
};
// 静态成员定义
int Obj::i = 10;
int Obj::j = 12;
// 为上面的类实现一个容器
class ObjContainer {
vector<Obj*> a;
public:
void add(Obj* obj)
{
a.push_back(obj); // 调用向量的标准方法
}
friend class SmartPointer;
};
// 实现智能指针,用于访问类 Obj 的成员
class SmartPointer {
ObjContainer oc;
int index;
public:
SmartPointer(ObjContainer& objc)
{
oc = objc;
index = 0;
}
// 返回值表示列表结束
bool operator++() // 前缀版本
{
if(index >= oc.a.size() - 1) return false;
if(oc.a[++index] == 0) return false;
return true;
}
bool operator++(int) // 后缀版本
{
return operator++();
}
// 重载运算符 ->
Obj* operator->() const
{
if(!oc.a[index])
{
cout << "Zero value";
return (Obj*)0;
}
return oc.a[index];
}
};
int main() {
const int sz = 10;
Obj o[sz];
ObjContainer oc;
for(int i = 0; i < sz; i++)
{
oc.add(&o[i]);
}
SmartPointer sp(oc); // 创建一个迭代器
do {
sp->f(); // 智能指针调用
sp->g();
} while(sp++);
return 0;
} //我也不熟