4,重载
4.1重载操作符
4.1.1重载左移操作符
左移操作符<<
#include<iostream>
using namespace std;
namespace test01
{
class Firsttest
{
public:
Firsttest& operator<<(const char* p)
{
cout << p;
return *this;
}
Firsttest& operator<<(const Firsttest& p)
{
cout << endl;
return *this;
}
Firsttest& operator<<(const int p)
{
cout << p;
return *this;
}
};
Firsttest printcout;
Firsttest endcout;
};
int main()
{
test01::printcout << "Hello" << test01::endcout;
test01::printcout << 1 << test01::endcout;
cin.get();
return 0;
}
4.1.2重载等号操作符
等号操作符=
#include<iostream>
using namespace std;
#include<string>
namespace test01
{
class Firsttest
{
public:
Firsttest()
{
m_string[0] = '\0';
}
void Print()
{
cout << m_string << endl;
}
Firsttest& operator=(const char* p)
{
strcpy_s(m_string, p);
return *this;
}
private:
char m_string[1024];
};
Firsttest printcout;
Firsttest endcout;
};
int main()
{
test01::printcout = "123456789";
test01::printcout.Print();
cin.get();
return 0;
}
4.1.2.1strcpy和strcpy_s
4.1.3重载操作符
可以重载的操作符
++ – == != > < + - / ^
4.2重载
c语言不支持重载,c++支持重载
#include<iostream>
using namespace std;
class FA
{
public:
static void Func1()
{
}
static void Func1(int a)
{
}
};
int main()
{
FA::Func1();
FA::Func1(1);
return 0;
}
实例化版本
#include<iostream>
using namespace std;
class FA
{
public:
void Func1()
{
}
void Func1(int a)
{
}
};
int main()
{
FA A;
A.Func1();
A.Func1(1);
return 0;
}
如果子类和父类有相同的函数,父类有很多此函数的重载时,实例化子类,编译器只会调用子类内的函数
解决方法:去掉(或更改名字)子类内的相同的函数,就可以调用父类的函数了
或者在子类中调用父类同名函数
class FB :public FA
{
public:
void Func1()
{
FA::Func1();
}
};
4.2.1任意参
#include <iostream>
#include <cstdarg>
// 定义一个函数,接受任意数量的整数参数
int sum(int count, ...)
{
int result = 0;
va_list args; // 定义一个va_list类型的变量
va_start(args, count); // 初始化va_list变量
// 使用va_arg逐个获取参数的值,并相加
for (int i = 0; i < count; i++)
{
int num = va_arg(args, int); // 获取下一个参数的值
result += num;
}
va_end(args); // 清理va_list变量
return result;
}
int main()
{
int s1 = sum(3, 1, 2, 3); // 传入3个参数
int s2 = sum(5, 1, 2, 3, 4, 5); // 传入5个参数
std::cout << "Sum 1: " << s1 << std::endl;
std::cout << "Sum 2: " << s2 << std::endl;
return 0;
}
4.2.2虚函数
加上virtual后先调用子类
#include<iostream>
using namespace std;
class FA
{
public:
virtual void Func1()
{
cout << "FA" << endl;
}
};
class FB :public FA
{
public:
void Func1() override
{
cout << "FB" << endl;
}
};
int main()
{
FB B;
B.Func1();
FA* p = &B;
p->Func1();
return 0;
}
输出结果:
FB
FB
如果去掉虚函数virtual和override
输出结果:
FB
FA
override作用
帮助编译器检测错误:如果派生类中的某个函数使用了override关键字来重写基类中的虚函数,但是由于函数签名不匹配等原因,无法找到对应的基类函数进行重写,编译器会提示错误。
提高代码可读性:使用override关键字可以明确地表明派生类中的函数是对基类中虚函数的重写,增强了代码的清晰度和可读性。
防止意外重定义:在派生类中,如果函数签名与基类中的虚函数不匹配,使用override关键字可以帮助我们发现错误,避免意外地创建了一个新的函数而不是对基类的重写。
4.2.2.1纯虚函数
当看到virtual void Func1() = 0;代码时,子类必须重写一遍,否则实例化时会报错
#include<iostream>
using namespace std;
class FA
{
public:
virtual void Func1() = 0;
};
class FB :public FA
{
public:
FB() {}
virtual void Func1();
};
void FB::Func1()
{
}
int main()
{
FB B;
return 0;
}
4.2.2.2final
final关键字在C++中用于限制派生类的进一步派生(继承)或重写
虚函数中的final关键字:使用final关键字修饰一个虚函数,可以禁止派生类对该虚函数的再重写。
成员函数中的final关键字:使用final关键字修饰一个成员函数,可以禁止派生类对该函数进行重写。
类中的final关键字:使用final关键字修饰一个类可以禁止其他类继承它,即该类不能作为其他类的基类。
#include<iostream>
using namespace std;
class FA
{
public:
virtual void Func1() = 0;
virtual void Func2() = 0;
};
class FB :public FA
{
public:
FB() {}
virtual void Func1()final;
virtual void Func2();
};
void FB::Func1(){}
void FB::Func2(){}
class FC :public FB
{
public:
FC() {}
//virtual void Func1();//因为父类使用了final,会报错
virtual void Func2();
};
void FC::Func2(){}
//因为FD的父类写了final,就不能继承了,所以不能有子类
/*class FD :public FC
{
public:
FD() {}
virtual void Func2();
};
void FD::Func2() {}*/
int main()
{
FB B;
FC C;
return 0;
}
4.2.2.3override
检测函数可以被重写与否
写在函数后面,检测是否可以被重写,不能就会报错
void Func2 override();
4.2.3虚函数原理
如果函数内什么也没有,编译器会为其分配1字节的空间,起到占位作用,
第二段代码同理,在空的情况下,编译器为其分配1字节的空间
第三段代码添加了一个int类型的a,编译器取消了占位的空间,输出结果为4字节
第四五六段代码的输出结果分别为4、8、8个字节,直接用函数不会占用内存,使用虚函数会占用内存(这4个字节储存的是虚函数指针)
1
#include<iostream>
using namespace std;
class FHello
{
public:
};
int main()
{
FHello o;
int len = sizeof(o);
cout << "大小 = " << len << "字节" << endl;
//输出结果:大小=1字节
return 0;
}
2
#include<iostream>
using namespace std;
class FHello
{
public:
};
class FHello1:public FHello
{
public:
};
int main()
{
FHello1 o;
int len = sizeof(o);
cout << "大小 = " << len << "字节" << endl;
//输出结果:大小=1字节
return 0;
}
3
#include<iostream>
using namespace std;
class FHello
{
public:
};
class FHello1:public FHello
{
public:
int a;
};
int main()
{
FHello1 o;
int len = sizeof(o);
cout << "大小 = " << len << "字节" << endl;
//输出结果:大小=4字节
return 0;
}
4
#include<iostream>
using namespace std;
class FHello
{
public:
void Test() {}//输出结果:大小=4字节
};
class FHello1 :public FHello
{
public:
int a;
};
int main()
{
FHello1 o;
int len = sizeof(o);
cout << "大小 = " << len << "字节" << endl;
return 0;
}
5
#include<iostream>
using namespace std;
class FHello
{
public:
virtual void Test01() {}//输出结果:大小=8字节
};
class FHello1 :public FHello
{
public:
int a;
};
int main()
{
FHello1 o;
int len = sizeof(o);
cout << "大小 = " << len << "字节" << endl;
return 0;
}
6
#include<iostream>
using namespace std;
class FHello
{
public:
virtual void Test01() {}
virtual void Test02() {}//输出结果:大小=8字节
};
class FHello1 :public FHello
{
public:
int a;
};
int main()
{
FHello1 o;
int len = sizeof(o);
cout << "大小 = " << len << "字节" << endl;
return 0;
}