C++ 多态
11. 多态
11.1 Conversions
- Public Inheritance should imply substitution
- If B isa A, you can use a B anywhere an A can be used.
- 示例:
#include <iostream>
using namespace std;
class A {
public:
int i;
public:
A():i(10) {}
};
class B: public A{
private:
int j;
public:
B():j(30){}
public:
void f() { cout << "B.j = " << j << endl; }
};
int main()
{
A a;
B b;
cout << a.i << " " << b.i << endl;
cout << sizeof(a) << " " << sizeof(b) << endl;
int *p = (int*)&a;
cout << p << " " << *p << endl;
*p = 20;
cout << a.i << endl;
p = (int*)&b;
cout << p << " " << *p << endl;
p++;
*p = 50;
b.f();
return 0;
}
11.2 Upcasting(向上造型)
- Upcasting is the act of converting from a Derived reference or pointer to a base class reference or pointer.
11.3 Polymorphism(多态)
- 示例:
class XYPos{...};
class Shape{
public:
Shape();
virtual ~Shape(); // 析构函数
virtual void render();
void move(const XYPos&);
virtual void resize();
protected:
XYPos center;
};
class Ellipse : public Shape {
public:
Ellipse(float maj, float minr);
virtual void render();
protected:
float major_axis, minor_axis;
};
class Circle : public Ellipse {
public:
Circle(float radius) : Ellipse(radius, radius) {}
virtual void render();
};
void render(Shape* p) {
p->render; // calls correct render function for given Shape!
}
void func() {
Ellipse ell(10, 20);
ell.render();
Circle circ(40);
circ.render();
render(&ell); // 调用 Ellipse 的 render
render(&circ); // 调用 Circle 的 render
}
11.3.1 多态特性
- Upcast:take an object of the derived class as an object of the base one.
- Dynamic binding:
- Binding: which function to be called
- Static binding: call the function as the code
- Dynamic binding: call the function of the object
- Binding: which function to be called
11.3.2 多态实现
- 编译命令:
g++ a.cpp -m32
#include <iostream>
using namespace std;
class A {
public:
A() : i(10) {}
virtual void f() { cout << "A::f() = " << i << endl; }
int i;
};
int main()
{
A a;
A b;
a.f();
cout << sizeof(a) << endl;
int *p = (int*)&a;
int *q = (int*)&b;
cout << *p << " " << *q << endl;
p++;
cout << *p << endl;
return 0;
}
- 示例二:
#include <iostream>
using namespace std;
class A {
public:
A() : i(10) {}
virtual void f() { cout << "A::f() = " << i << endl; }
int i;
};
class B: public A {
public:
B() : j(20) {}
virtual void f() { cout << "B::f() " << j << endl; }
int j;
};
int main()
{
A a;
B b;
A* p = &b;
p->f();
return 0;
}
11.3.3 Virtual destructors
- Make destructors virtual if they might be inherited
Shape *p = new Ellipse(100.0F, 200.0F);
delete p;
// Want Ellipse::~Ellipse() to be called
// 1, Must declare Shape::~Shape() virtual
// 2, It will call Shape::~Shape() automatically
// If Shape::~Shape() is not virtual, only Shape::~Shape() will be invoked!
11.3.4 Overriding
- Overriding redefines the body of a virtual function
class Base {
public:
virtual void func();
};
class Derived : public Base {
public:
virtual void func();
// overrides Base::func()
}
// 子类中调用父类方法
void Derived::func() {
cout << "In Derived::func!";
Base::func();
}
- 示例二:
class Expr {
public:
virtual Expr* newExpr();
virtual Expr& clone();
virtual Expr self();
};
class BinaryExpr : public Expr {
public:
virtual BinaryExpr* newExpr(); // OK
virtual BinaryExpr& clone(); // OK
virtual BinaryExpr self(); // Error!
}
11.3.5 Overloading and virtuals
- Overloading adds multiple signatures
- If you override an overloaded function, you must override all of the variants!
- Can't override just one
- If you don't override all, some will be hidden
class Base {
public:
virtual void func();
virtual void func(int);
};
参考资料: