静多态
面向对象编程
其实
面向对象编程
(Object-Oriented Programming)中也表现为
函数重载
和运算符重载。
class Complex {
public:
Complex() : m_real(0), m_image(0) { };
Complex(double real, double image) : m_real(real), m_image(image) { };
staticvoid staticFunc()
{
std::cout << "staticFunc()" << std::endl;
}
staticvoid staticFunc(int oneParam)
{
std::cout << "staticFunc(int oneParam)" << std::endl;
}
virtualvoid virtualFunc()
{
std::cout << "virtualFunc()" << std::endl;
}
virtualvoid virtualFunc(int oneParam)
{
std::cout << "virtualFunc(int oneParam)" << std::endl;
}
friendvoid friendFunc();
friendvoid friendFunc(int oneParam);
//
运算符重载
:Comple + Comple
// Complex + Complex成员版本:允许一个complex对象和另一个Complex对象相加
Complex operator + (const Complex& elem)
{
return Complex(m_real + elem.m_real, m_image + elem.m_image);
}
// Complex + double成员版本:允许一个complex对象和另一个double对象相加
// 只能是Complex + double,不能是double + Complex
Complex operator + (double elem)
{
return Complex(m_real + elem, m_image);
}
// Complex + Complex
友元
版本:允许一个complex对象和另一个Complex对象相加
friend Complex operator + (const Complex& lsh, const Complex& rhs)
{
return Complex(lsh.m_real + rhs.m_real, lsh.m_image + rhs.m_image);
}
// Complex + double
友元
版本:允许一个complex对象和另一个double对象相加
// 只能是Complex + double,不能是double + Complex
friend Complex operator + (const Complex& lsh, double rhs)
{
return Complex(lsh.m_real + rhs, lsh.m_image);
}
// double + Complex
友元
版本:允许一个double对象和另一个Complex对象相加
//只能是double + Complex,不能是Complex + double
//和上面的Complex + double
友元
版本相辅相成
friend Complex operator + (double lhs, const Complex& rhs)
{
return Complex(lhs + rhs.m_real, rhs.m_image);
}
private:
double m_real;
double m_image;
};
void friendFunc()
{
std::cout << "virtualFunc()" << std::endl;
}
void friendFunc(int oneParam)
{
std::cout << "virtualFunc(int oneParam)" << std::endl;
}
注:见Complex类定义中的
运算符重载
部分!
静多态
泛型编程
在C++中,
泛型编程
(Generic Programming) 是通关过
模板
来实现的,然而模板不是与上述两种编程范例有所不同,它必须依附于上述的某种范例,在某范例的基础上来实现,就像
面向对象
和过程化编程的关系一样。下面就是
模板
分类:
按泛化对象可分为:
template
class List {
// ...
};
List iList; // iList是能够存储int
类型
的
链表
对象
template
class Bit {
// ...
};
Bit<3> bit3; // bit3是长度为3位的位对象
3)
数值
和
类型
泛化(Type & Value):
template
class Array {
// ...
};
Array iArray3; // iArray3是能够存储3个int
类型
的
数组
对象
按泛化的载体可分为:
template
void functionGeneric()
{
// ...
}
template
class classGeneric {
// ...
};
优缺点比较
静多态是以牺牲灵活性而获得运行速度的一种做法;而动多态则恰恰相反,它是以牺牲运行速度而获取灵活性的做法。当然这么说是不全面的,看看下面这个特殊的应用:
使用静多态来实现动多态
这是一种在
模板元
编程(Template Metaprogramming)中常见的标准编程技巧。在C++中,可以借助
模板
来实现
面向对象语言
所支持动多态相似的功能特性(C++中指的就是的virtual 函数)。
下面是C++本身所支持多态形式:(virtual版)
#include
class Base {
public:
virtual void method() = 0;
virtual ~Base() { }
};
class Derived : public Base {
public:
virtual void method()
{
std::cout << "Derived" << std::endl;
}
};
class Derived2 : public Base {
public:
virtual void method()
{
std::cout << "Derived2" << std::endl;
}
};
int main()
{ Base *pBase = new Derived;
pBase->method(); // 输出:"Derived"
delete pBase;
Base *pBase2 = new Derived2;
pBase2->method(); // 输出:"Derived2"
delete pBase2;
return 0;
}
注:C++本身是借助virtual
关键字
来实现多态的(dynamic polymorphism),而通常
编译器
是借助virtual look-up tables(
虚函数表
)来决定该调用那个版本的函数,当然这一过程发生在运行期。
下面是使用CRTP(Curiously Recurring Template Pattern)来实现多与上面对应功能的静多态代码:
#include
template
class Base {
public:
void method()
{
// ...
static_cast(this)->implementation();
// ...
}
};
class Derived : private Base {
public:
void implementation()
{
std::cout << "Derived" << std::endl;
}
};
class Derived2 : private Base {
public:
void implementation()
{
std::cout << "Derived2" << std::endl;
}
};
int main()
{
Base *pBase = new Base();
pBase->method(); // 输出:"Derived"
delete pBase;
Base *pBase2 = new Base();
pBase2->method(); // 输出:"Derived2"
delete pBase2;
return 0;
}
虽然使用这种方式实现的多态和
面向对象
中的多态从功能上说差不多相同,但是前者没有后者易用、易懂、和能力强大。虽然如此,CRTP作为一种
模板
设计模式还是很有用的,例如,Boost iterator library就是用了这种方法来实现。
其实在别的语言中也存在CRTP这种模式,如Java,Enum类被定义为Enum>,当然由于Java在
模板
方面的不足,作为Java语言的使用者,你是没法自己体验这样的用法(Java虽然支持模板特性,但是用户不能自己定义模板,只能使用库里边的
模板类
)。