静态重载
编译器根据函数的参数的数量、类型或者顺序 的不同,从而确定调用哪个函数。
在C++中,重载(overloading)是指有多个同名函数,但它们的参数列表(参数的数量、类型或者顺序)不同。这使得我们可以为同一个操作提供不同的实现,以适应不同的输入数据类型或数量。
在C++中,通常所说的“重载”是指静态重载(static overloading),这是在编译时根据函数的参数列表来决定调用哪个函数的过程。静态重载是由编译器完成的,它确保了每个重载函数都有独一无二的参数类型组合。
重载的基本规则是,重载的函数必须在参数列表上有差异,不能仅仅基于返回类型的不同来进行重载。例如:
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
在这个例子中,Calculator
类有三个名为 add
的重载函数。第一个接受两个 int
参数,第二个接受两个 double
参数,而第三个接受三个 int
参数。
编译器会根据传递给函数的参数类型和数量来确定调用哪个函数。这允许我们为同一个操作提供多种实现,同时保持函数名称的一致性和代码的可读性。
重载不仅限于类成员函数,也可以用于自由函数(非成员函数)。此外,构造函数也可以被重载,以提供不同的对象创建方式。
重载是C++面向对象编程的核心特性之一,它允许我们以统一的方式处理不同类型的数据,提高了代码的复用性和灵活性。
动态重载
动态重载(dynamic overloading),通常指的是在运行时根据对象的实际类型来决定调用哪个函数的过程,这通常与多态和虚函数相关。在C++中,这是通过虚函数和继承实现的,允许我们在运行时通过基类的指针或引用来调用子类的函数。
例如,考虑以下代码:
class Base {
public:
virtual void function() {
std::cout << "Base function" << std::endl;
}
};
class Derived : public Base {
public:
void function() override {
std::cout << "Derived function" << std::endl;
}
};
int main() {
Base* b = new Derived();
b->function(); // 运行时动态重载,调用Derived::function
delete b;
}
在这个例子中,function
是一个虚函数,它在基类 Base
中被声明,并在派生类 Derived
中被重写。当我们通过基类指针 b
来调用 function
时,由于虚函数的特性,将在运行时根据 b
实际指向的对象类型来决定调用哪个版本的 function
。
操作符重载(静态重载)
在C++中,操作符重载(operator overloading)是一种特殊的重载形式,它允许我们为类定义新的操作符含义,使得类的对象可以使用标准操作符进行操作,如算术操作符、比较操作符、赋值操作符等。
操作符重载可以让类的使用更加直观和方便,因为它允许我们以自然的语法来操作对象。例如,我们可以重载加法操作符 +
来实现两个复数对象的相加。
下面是一个简单的操作符重载的例子:
class Complex {
public:
double real;
double imag;
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
// 重载加法操作符
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
// 重载输出操作符
friend std::ostream& operator<<(std::ostream& out, const Complex& c);
};
std::ostream& operator<<(std::ostream& out, const Complex& c) {
out << c.real << "+" << c.imag << "i";
return out;
}
int main() {
Complex c1(1.0, 2.0);
Complex c2(2.0, 3.0);
Complex c3 = c1 + c2;
std::cout << "c3: " << c3 << std::endl;
return 0;
}
在这个例子中,我们定义了一个 Complex
类来表示复数,并重载了加法操作符 +
和输出操作符 <<
。这样,我们就可以直接使用 +
来对两个 Complex
对象进行加法运算,并且可以使用 <<
将 Complex
对象输出到标准输出流中。
操作符重载可以让类的接口更加友好,使得类的使用更加符合直觉。然而,重载操作符时应该谨慎,确保重载的操作符的行为对于用户来说是直观和合理的,以避免混淆和误用。
注意事项:
- 系统内置的类型运算 不能被改变
- 算符重载的函数应该有明确的返回类型,通常是对象的引用或者常量引用,以便支持连续的操作
- 运算符重载函数的参数个数和类型必须与原始运算符一致或兼容
- 如果运算符重载函数作为类的成员函数,它可以直接访问类的私有成员;如果作为友元函数,可能需要通过友元关系来访问私有成员
- 自增(++)和自减(--)运算符有前缀形式和后缀形式,需要分别进行重载
- 如果需要在自定义类上使用<<和>>运算符,通常将它们声明为友元,并返回std::ostream&和std::istream&
ps:
在C++中,std::ostream
是一个抽象的流类型,它表示输出流。std::cout
是 std::ostream
的一个实例,它是标准输出流,通常与控制台(终端)关联。然而,C++的I/O库是设计得非常灵活的,允许你将输出重定向到其他地方,比如文件或者字符串。
当你看到函数参数为 std::ostream& out
时(其实这里的out可以换成其他名字嘿嘿),这意味着这个函数可以接受任何类型的输出流作为参数,而不仅仅是 std::cout
。这使得同一个函数可以用于输出到控制台、文件或其他任何输出流。
例如,你可以使用这样的函数来输出到文件:
void print(std::ostream& out) {
out << "Hello, World!" << std::endl;
}
int main() {
print(std::cout); // 输出到控制台
std::ofstream file("output.txt");
print(file); // 输出到文件
return 0;
}
在这个例子中,print
函数接受一个 std::ostream&
参数,允许你将输出重定向到任何地方。在 main
函数中,我们首先将输出打印到控制台,然后创建一个文件输出流 std::ofstream
,并将输出重定向到文件 "output.txt"。
这种设计使得C++的I/O系统非常灵活和可扩展。通过使用引用(&
),我们还可以避免不必要的拷贝,提高程序的效率。
相关代码:
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class student
{
public:
string name;
int age;
student(string n,int a):name(n),age(a){}
int operator+(int number)
{
return this->age+number;
}
};
void f()
{
int a=10;
student obj1("czy",24);
int b=obj1+a;
cout<<"年龄加起来多少岁?"<<b<<endl;
}
class Person {
public:
Person() {};
Person(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
//成员函数实现 + 号运算符重载
Person operator+(const Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
public:
int m_A;
int m_B;
};
//全局函数实现 + 号运算符重载
//Person operator+(const Person& p1, const Person& p2) {
// Person temp(0, 0);
// temp.m_A = p1.m_A + p2.m_A;
// temp.m_B = p1.m_B + p2.m_B;
// return temp;
//}
//运算符重载 可以发生函数重载
Person operator+(const Person& p2, int val)
{
Person temp;
temp.m_A = p2.m_A + val;
temp.m_B = p2.m_B + val;
return temp;
}
void test() {
Person p1(10, 10);
Person p2(20, 20);
//成员函数方式
Person p3 = p2 + p1; //相当于 p2.operaor+(p1)
cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;
Person p4 = p3 + 10; //相当于 operator+(p3,10)
cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl;
}
class Complex {
public:
double real;
double imag;
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
// 重载加法操作符
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
// 重载输出操作符
friend std::ostream& operator<<(std::ostream& out, const Complex& c);
};
std::ostream& operator<<(std::ostream& out, const Complex& c) {
out << c.real << "+" << c.imag << "i";
return out;
}
int main() {
Complex c1(1.0, 2.0);
Complex c2(2.0, 3.0);
Complex c3 = c1 + c2;
std::cout << "c3: " << c3 << std::endl;
return 0;
}