1 动态绑定
在C++中,默认不会触发动态绑定,如果需要触发动态绑定,那么就需要:
1)将函数指定为虚函数;
2)通过基类的指针或引用调用该函数
class Base {
public:
virtual void f() {
cout <<"Base f()" << endl;
}
~Base() {}
}
class Derived {
public:
void f() {
cout <<"Derived f()" << endl;
}
~Derived() {}
}
int main() {
Base b;
b.f();//Base f()
Derived d;
d.f();//Derived f()
Base* bp = new Derived();
bp->f();//Derived f()动态绑定,如果不是virtual,那么输出会是Base f()
}
注意以上代码中:如果f()不是virutal函数,那么bp->f(),不会动态绑定,执行的将是Base的f()。
class Base {
public:
Base() {
cout <<"Base ctor" << endl;
}
void f() {
cout <<"Base f()" << endl;
}
};
class Derived : public Base {
public:
Derived() {
cout << "Derived ctor" << endl;
}
void f() {
cout <<"Derived f()" << endl;
}
};
int main(int argc, const char * argv[]) {
Base* bp = new Derived();
bp->f();//由于不是virtual,执行的将是Base::f()
}
2 基类指定为virtual,子类都会是virtual
3 virutal 析构函数
如果在类继承层次结构上要正确的释放资源,调用析构函数,那么必须将析构函数都声明为virutal
class Base {
public:
~Base() {
cout << "~Base()" << endl;
}
}
class Derived {
public:
void f() {
cout <<"Derived f()" << endl;
}
~Derived() {
cout <<"~Derived()" << endl;
}
}
int main() {
Base* bp = new Derived();
delete bp;
}
运行结果:
~Base()
由于析构函数不是virtual,子类的析构函数不会被调用。这样就出现问题了。所以建议对所有的类,析构函数都设置为virtual。
4 纯虚函数
纯虚函数类似java中的interface或者abstract class抽象类的效果
class Base {
public:
virtual f() = 0;
~Base() {}
}
带有纯虚函数的类,不能被实例化,通常作为基准接口来使用。子类覆写纯虚函数才可以实例化。
5 虚继承
C++中多重继承,会出现交叉继承的问题(也就是菱形继承结构)。
class Base {
public:
Base() {
cout <<"Base ctor" << endl;
}
virtual void f() {
cout <<"Base f()" << endl;
}
};
class Derived1 : virtual public Base {
public:
Derived1() {
cout <<"Derived1 ctor" << endl;
}
};
class Derived2 : virtual public Base {
public:
Derived2() {
cout <<"Derived2 ctor" << endl;
}
};
class CommonDerived: public Derived1, public Derived2 {
};
int main(int argc, const char * argv[]) {
CommonDerived c;
c.f();//这里可以编译通过,因为继承的时候,使用了virtual,同时Derived1/Derived2也没有覆写f()
}
上面的代码可以编译通过:
1)因为Derived1/Derived2都 虚继承于Base;
2)Derived1/Derived2/CommonDerived都没有覆写f(),只要有一个覆写,那么都无法编译通过;
3)此时c.f()等价于 c.Base::f()/c.Derived1::f()/c.Derived2::f()/c.CommonDerived::f();