1、运行前就完成的联编称为静态联编:函数重载、运算符重载实现!
程序运行时才完成的联编为动态联编:继承、虚函数实现!
2、运算符重载
(1)类以外的运算符重载:只能访问类中的公有数据成员
#include<iostream>
using namespace std;
class Complex{
public:
double real;
double imag;
Complex(double r = 0, double i = 0){
real = r;
imag = i;
}
};
Complex operator+(Complex co1, Complex co2){//类以外运算符重载
Complex temp;
temp.real = co1.real + co2.real;
temp.imag = co1.imag + co2.imag;
return temp;
}
int main(){
Complex co1(1.1,2.2), co2(2.2,3.3), result;
result = co1 + co2;
cout<<result.real<<" "<<result.imag<<endl;
}
(2)友元运算符函数
#include<iostream>
using namespace std;
class Complex{
private:
double real;
double imag;
public:
Complex(double r = 0, double i = 0){
real = r;
imag = i;
}
void print();
//用友元运算符函数重载+
friend Complex operator+(Complex a, Complex b);
};
Complex operator+(Complex co1, Complex co2){
Complex temp;
temp.real = co1.real + co2.real;
temp.imag = co1.imag + co2.imag;
return temp;
}
void Complex::print(){
cout<<real;
if(imag>0) cout<<"+";
if(imag!=0) cout<<imag<<"i"<<endl;
}
int main(){
Complex co1(1.1,2.2), co2(2.2,3.3), result;
result = co1 + co2;
result.print();
}
(3)成员运算符函数
#include<iostream>
using namespace std;
class Complex{
private:
double real;
double imag;
public:
Complex(double r = 0, double i = 0){
real = r;
imag = i;
}
void print();
//用成员运算符函数重载+
Complex operator+(Complex b);
};
Complex Complex::operator+(Complex co1){
Complex temp;
temp.real = co1.real + real;
temp.imag = co1.imag + imag;
return temp;
}
void Complex::print(){
cout<<real;
if(imag>0) cout<<"+";
if(imag!=0) cout<<imag<<"i"<<endl;
}
int main(){
Complex co1(1.1,2.2), co2(2.2,3.3), result;
result = co1 + co2;
result.print();
}
3、成员运算符函数与友元运算符函数的比较
(1)双目运算符,成员一个参数,友元两个参数;单目,成员0个,友元1个参数。
(2)双目,一般两者都可以。有一种情况必须用友元运算符
ob = ob + 100; //right
ob = 100 + ob; //wrong 做操作数是一个整数,而整数是一个内部数据类型,不能产生对成员运算符函数的调用,而友元能规避这个问题!
4、类类型与系统预定义类型间的转换
(1) 通过构造函数进行类型转换
#include<iostream>
using namespace std;
class example{
private:
int num;
public:
example(int);
void print();
};
example::example(int n){
num = n;
cout<<"Initializing with:"<<num<<endl;
}
void example::print(){
cout<<"num= "<<num<<endl;
}
int main(){
example X = example(3);//由int型向example类类型转换
X.print();
cout<<endl;
example Y = 3;//同理
Y.print();
}
(2) 通过类类型转换函数进行类型转换
#include<iostream>
using namespace std;
class Complex{
public:
Complex(int r, int i){
real = r;
imag = i;
cout<<"constructing..."<<endl;
}
Complex(int i=0){
real=imag=i/2;
}
operator int(){
cout<<"Type changed to int..."<<endl;
return real+imag;
}
void print(){
cout<<real<<" "<<imag<<endl;
}
private:
int real;
int imag;
};
int main(){
Complex a(1,2), b(3,4);
a.print();
a.print();
Complex c;
c = a + b;//a,b先转换为3,7,得到c=10,再通过构造函数进行类型转换
c.print();
return 0;
}
输出:
constructing...
constructing...
1 2
1 2
Type changed to int...
Type changed to int...
5 5
5、虚函数:允许函数调用与函数体之间的联系在运行时才建立,即是动态联编
virtual只能对基类中public或protected部分的成员声明为虚函数
#include<iostream>
using namespace std;
class base{
int a;
public:
base(int x){
a = x;
}
virtual void show(){//定义虚函数
cout<<"base "<<a<<endl;
}
};
class sub: public base{
int c;
public:
sub(int x, int y):base(x){
c = y;
}
void show(){//重新定义虚函数
cout<<"sub "<<c<<endl;
}
};
int main(){
base b(19), *bp;
sub s(1,2);
bp = &b;
bp->show();//调用基类的show()
bp = & s;
bp->show();//调用子类的show()
return 0;
}
每个类都维护一张虚函数表 http://www.uml.org.cn/c++/200811143.asp
纯虚函数:一个在基类中说明的虚函数,但是没有定义,要求在派生类中定义或者重新声明为纯虚函数。
virtual 函数类型 函数名(参数表)= 0;
如果一个类中有一个纯虚函数就为抽象类。
(1)抽象类至少有个纯虚函数,因此抽象类只能用作基类,不能建立抽象类对象(同java)
(2)抽象类不能用作参数类型、函数返回类型或显示转换的类型。但可以声明指向抽象类的指针或引用,此指针可以指向它的派生类,进而实现多态性。
(3)不允许具体类派生出抽象类