第五次作业--运算符重载与虚函数
运算符重载
-
定义:对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同行为,其实质就是函数重载
-
规则:
(1)C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已经有的运算符(不能重载的运算符:成员访问符 "." 、成员指针运算符". *" 、作用域分辨符"::" 、三目运算符"?😊
(2)重载之后运算符的优先级和结合性不会改变
(3)运算符的重载是由于对新的数据类型有需求,所以对原有运算符进行改造,所以重载功能应与原有功能相似,不能改变原有运算符的操作对象个数,同时至少要有一个操作对象是自定义类型
-
语法:
-
注意:
(1)当以非成员函数进行重载时,有时需要访问运算符所涉及的私有成员,这是可以把该函数声明为类的友元函数
(2)当运算符重载为类的成员函数时,函数参数个数要比原来的参数少一个(后置"++" "--"除外);为非成员函数时,参数与原有的相同
(3)前置“++” “--”和后置“++” “--”:成员函数形参:没有形参;非成员函数:重载函数有一个int类型
- 程序
以双目运算符重载,实现Counter类的相加和整数与类相加(成员函数)、相减(非成员函数)
#include<iostream>
#include<Windows.h>
using namespace std;
class Counter;
class Counter
{
public:
Counter(int data=0) :data(data) {};
Counter operator +(Counter &p);//一个参数,另外一个参数为this所指的对象
Counter operator +(int);
friend Counter operator -(Counter &p, const int a);//两个参数,保持不变
inline void Show() const;
private:
int data;
};
//类与类相加,Counter 自定义类型
Counter Counter::operator+(Counter &p)
{
data = data + p.data;
return (*this);
}
Counter Counter::operator+(int a)
{
data = data + a;
return (*this);
}
void Counter::Show() const
{
cout<< data << endl;
}
Counter operator - (Counter &p, const int a)
{
Counter pt;
pt.data = p.data - a;
return a;
}
int main()
{
Counter c1(5);
Counter c2;
Counter c3;
cout << "The Origin Of c1:";
c1.Show();
cout << "The Origin Of c2:";
c2.Show();
c1 + 5;
cout << "c1=c1+5=";
c1.Show();
c3=c1 - 5;
cout << "c1-5=";
c3.Show();
c2 + c1;
cout << "c2=c2+c1=";
c2.Show();
system("pause");
return 0;
}
运行结果
单目运算符重载,实现Point类的前置"++"、后置"++"、前置"--"、后置"--",运用引用,节省内存,不用再创建一个对象,进行保存
#include<iostream>
#include<Windows.h>
using namespace std;
class Point
{
public:
Point(double x = 0, double y = 0) :x(x), y(y) {};
Point & operator ++();
Point &operator ++( const int);
Point & operator --();
Point &operator --(const int);
inline void Show() const;
private:
double x, y;
};
//功能:实现前置++
Point &Point::operator++()
{
++x;
++y;
return *this;
}
//功能:实现后置++
Point& Point::operator++(const int)
{
Point old(*this);
++(*this);
return old;
}
//功能:实现前置--
Point & Point::operator--()//引用用于返回一个地址,就不用在多创建对象,消耗内存
{
--x;
--y;
return *this;
}
//功能:实现后置--
Point &Point::operator--(const int)
{
Point old = (*this);
--(*this);
return old;
}
//功能:显示点的坐标
inline void Point::Show() const
{
cout << "(" << x << "," << y << ")" << endl;
}
int main()
{
//测试前置++和后置--
Point p1(3, 4);
Point p2;
cout << "The Origin Of P1 :";
p1.Show();
//p1前置++
++p1;
cout << "++P1 =";
p1.Show();
//p1后置++
p2 = p1++;
cout << "P2=P1++ =";
p2.Show();
cout << "P1++ =";
p1.Show();
//测试前置--和后置--
Point p3(8, 9);
Point p4;
cout << "The Origin Of P3 :";
p3.Show();
//p3前置++
--p3;
cout << "--P3 =";
p3.Show();
//p3后置--
p4 = p3--;
cout << "P4=P3-- =";
p4.Show();
cout << "P3-- =";
p3.Show();
system("pause");
return 0;
}
运行结果
虚函数和抽象类
虚函数可以用于实现多态,而多态的条件有3:(1)满足兼容规则(2)要声明虚函数(3)成员函数的调用通过指针、引用访问
-
一般虚函数
(1)语法:virtual 函数类型 函数名(形参表)
(2)注意:函数声明只能在类的定义中的函数原型声明中,不能在成员函数实现时
(3)虚函数一般不声明成内联函数,因为对虚函数调用是需要动态绑定,而内联函数的处理为静态,所以一般不将虚函数声明成内联函数 -
纯虚函数
(1)语法:virtual 函数类型 函数名(形参表)=0
(2)定义为纯虚函数后在基类可以不给出函数的实现部分,由派生类给出不同的函数实现,从而实现多态 -
抽象类
(1)具有纯虚函数的类叫抽象类
(2)抽象类不能实例化,即不能生成对象
- 程序
以Shape(抽象类)作为基类,派生出_Rectangle和Circle类,使用指针进行对象的访问
头文件定义
class Shape//抽象类Shape
{
public:
virtual double getArea() const=0;
virtual double getPerim() const=0;
};
class _Rectangle :public Shape
{
public:
_Rectangle(float length, float width) :length(length), width(width) {};
double getArea() const;
double getPerim() const;
inline void Show() const;
private:
float length;
float width;
};
class Circle :public Shape
{
public:
Circle(float Radius) :Radius(Radius) {};
double getArea() const;
double getPerim() const;
inline void Show() const;
private:
double Radius;
};
头文件实现和main函数实现
#include<iostream>
#include<Windows.h>
#include<cstdlib>
#include"8-6.h"
constexpr auto PI = 3.1415926;
using namespace std;
double _Rectangle::getArea() const
{
return (length * width);
}
double _Rectangle::getPerim() const
{
return (2 * length + 2 * width);
}
inline void _Rectangle::Show() const
{
cout << "The Area Of Rectangle :" << getArea() << endl;
cout << "The Perim Of Rectangle :" << getPerim() << endl;
}
double Circle::getArea() const
{
return (Radius *Radius *PI);
}
double Circle::getPerim() const
{
return (2 * Radius*PI);
}
inline void Circle::Show() const
{
cout << "The Area Of Circle : " << getArea() << endl;
cout << "The Perim Of Circle : " << getPerim() << endl;
}
void fun(Shape *ptr)
{
ptr->getArea();
ptr->getPerim();
}
int main()
{
//测试:Shape不能实例化
//Shape p;
_Rectangle s(3, 4);
//通过对象操作
/*s.getArea();
s.getPerim();*/
//通过指针操作,运用虚函数,使指针指向对所引用的对象
fun(&s);
s.Show();
Circle c(3);
/*c.getArea();
c.getPerim();*/
fun(&c);
c.Show();
system("pause");
return 0;
}
运行结果