重载与多态
一.运算符重载
定义:运算符重载是对已有运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。例如:
在这样一段程序中,我们对a,b进行加法运算,
# include < iostream > using namespace std; class Counter {public : Counter() {}; Counter(int i) { count = i; } private : int count; }; int main() { Counter a(1),b(2),c; cout << "a=" << a<<endl; cout << "b=" << b << endl; c = a + b; cout << "c=" <<c << endl; system("pause"); return 0; }
会出现这样的错误
这时候就需要运算符重载
1.1
运算符重载的规则:(1)c++中的运算符大多可以重载,而且只能重载已有运算符。
(2)重载之后运算符优先级和结合性都不会改变。
(3)运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。
运算符重载为类的成员函数的语法形式:
返回类型 operater 运算符{形参表}
{
函数体
}
以非成员函数重载的语法与之相同,但有时访问涉及到私有成员,可以将函数声明为友元函数。例如:
# include < iostream > using namespace std; class Counter {public : Counter() {}; Counter(int i) { count = i; } friend Counter operator+(const Counter & c1, const Counter & c2); friend ostream& operator<< (ostream & cout, Counter&c1); private : int count; }; Counter operator + (const Counter & c1, const Counter & c2) { return Counter (c1.count+c2.count); } ostream& operator<< (ostream & cout, Counter&c1) { cout << c1.count; return cout; } int main() { Counter a(1),b(2),c; cout << "a=" << a<<endl; cout << "b=" << b << endl; c = a + b; cout << "c=" <<c << endl; system("pause"); return 0; }
结果:
注意:当运算符重载为类的成员函数时,函数的参数比原来的操作个数少一个;重载为非成员函数时参数个数与原操作数相同
1.2运算符重载成员函数和非成员函数
以将单目运算符++重载为例,
成员函数:
# include< iostream > using namespace std; class Complex { public: Complex(double r = 0.0, double i = 0.0) :real(r), imag(i) {} Complex operator++()const; Complex operator++(int)const; void display() { cout<<"real:"<<real <<"imag:"<<imag<<endl; } private: double real, imag; }; Complex Complex ::operator++()const { Complex c; (*this)++; c.real=this->real; c.imag = this->imag; return c; } Complex Complex:: operator++( int)const{ Complex c=*this; c.real++; c.imag++; return c; } int main() { Complex c1(5, 4), c2, c3; cout << "c1="; c1.display(); c2 = ++c1; cout << "c2=" ; c2.display(); c3 = c1++; cout << "c3=" ; c3.display(); system("pause"); }
在本例中前置与后置最大的不同在于有无形参,其他的与普通的成员函数,没有什么区别只是++这个运算符能做用于不同的对象上,有了更广泛的多态特征。
非成员函数:
因访问私有成员,声明为友元函数
# include< iostream > using namespace std; class Complex { public: Complex(double r = 0.0, double i = 0.0) :real(r), imag(i) {} friend Complex operator++(Complex &c1); friend Complex operator++(Complex &c1,int); void display() { cout<<"real:"<<real <<"imag:"<<imag<<endl; } private: double real, imag; }; Complex operator++(Complex &c1) { Complex c; c1.real++; c1.imag++; c.real= c1.real; c.imag = c1.imag; return c; } Complex operator++(Complex &c1, int){ Complex c; c.real = c1.real; c.imag = c1.imag; c1.real++; c1.imag++; return c; } int main() { Complex c1(5, 4), c2, c3; cout << "c1="; c1.display(); c2 = ++c1; cout << "c2=" ; c2.display(); c3 = c1++; cout << "c3=" ; c3.display(); system("pause"); }
结果:
二.多态
定义:指同样的消息被不同类型对象接受时导致的不同行为。在实现时可以分为静态多态和动态多态。
静态多态:在编译过程中确定了同名操作的具体操作对象,例如重载。
动态多态:运行过程才动态的确定操作针对的对象,例如虚函数。
2.1虚函数
虚函数是动态绑定的基础。是非静态的成员函数。
语法:virtual 函数类型 函数名{形参表};
而运行多态需要满足三个条件:(1)满足赋值兼容规则。(2)声明虚函数。(3)用成员函数调用或者是通过指针或者引用来访问。
例:
# include < iostream > using namespace std; class Mammal { public: Mammal() { cout << "constructors Mammal"<<endl; }; ~Mammal() { cout << "destructing Mammal"<<endl; }; virtual void Speak() const { cout << "Mammal sound!\n"; }
};
class Dog : public Mammal
{
public:
Dog() { cout << "constructors Dog" << endl; };
~Dog() { cout << "destructing Dog" << endl; }; void Speak() const { //覆盖基类的虚函数 cout << "Dog sound!\n"; }
};
void fun(Mammal*p) {
p->Speak();
}
int main()
{
Dog d;
fun(&d);;
system("pause");
return 0;
}
可见函数成员speak()声明为虚函数,覆盖了基类的虚函数如需访问基类使用指针,这样,能够对同一类族中的对象进行统一处理,抽象程度更高,更简洁,高效。
2.2虚析构函数
语法:virtual ~类名();
虚析构函数是为了彻底释放内存,防止内存泄露
1
1
1
1
1
1