private的虚函数
3.1 private的虚函数
考虑下面的例子:
class A
{
public:
void foo() { bar();}
private:
virtual void bar() { ...}
};
class B: public A
{
private:
virtual void bar() { ...}
};
在这个例子中,虽然bar()在A类中是private的,但是仍然可以出现在派生类中,并仍然可以与public或者protected的虚函数一样产生多态的效果。并不会因为它是private的,就发生A::foo()不能访问B::bar()的情况,也不会发生B::bar()对A::bar()的override不起作用的情况。
这种写法的语意是:A告诉B,你最好override我的bar()函数,但是你不要管它如何使用,也不要自己调用这个函数。
3.2 构造函数和析构函数中的虚函数调用
一个类的虚函数在它自己的构造函数和析构函数中被调用的时候,它们就变成普通函数了,不“虚”了。也就是说不能在构造函数和析构函数中让自己“多态”。
例如:
class A
{
public:
A() { foo();} // 在这里,无论如何都是A::foo()被调用!
~A() { foo();} // 同上
virtual void foo();
};
class B: public A
{
public:
virtual void foo();
};
void bar()
{
A * a = new B;
delete a;
}
如果你希望delete a的时候,会导致B::foo()被调用,那么你就错了。同样,在new B的时候,A的构造函数被调用,但是在A的构造函数中,被调用的是A::foo()而不是B::foo()。
3.3 多继承中的虚函数
3.4 什么时候使用虚函数
在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的。从设计的角度讲,出现在基类中的虚函数是接口,出现在派生类中的虚函数是接口的具体实现。通过这样的方法,就可以将对象的行为抽象化。
以设计模式[2]中Factory Method模式为例,Creator的factoryMethod()就是虚函数,派生类override这个函数后,产生不同的Product类,被产生的Product类被基类的AnOperation()函数使用。基类的AnOperation()函数针对Product类进行操作,当然Product类一定也有多态(虚函数)。
另外一个例子就是集合操作,假设你有一个以A类为基类的类层次,又用了一个std::vector来保存这个类层次中不同类的实例指针,那么你一定希望在对这个集合中的类进行操作的时候,不要把每个指针再cast回到它原来的类型(派生类),而是希望对他们进行同样的操作。那么就应该将这个“一样的操作”声明为virtual。
现实中,远不只我举的这两个例子,但是大的原则都是我前面说到的“如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的”。这句话也可以反过来说:“如果你发现基类提供了虚函数,那么你最好override它”。
附:C++中的虚函数和纯虚函数用法
1.虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能被称为抽象类(abstract class)。
2.虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在子类(sub class)中实现该函数才可以使用,因为纯虚函数在基类(base class)
只有声明而没有定义(#add 错,可以有定义)。
3.虚函数和纯虚函数都可以在子类(sub class)中被重载,以多态的形式被调用。
4.虚函数和纯虚函数通常存在于抽象基类(abstract base class -ABC)之中,被继承的子类重载,目的是提供一个统一的接口。
5.虚函数的定义形式:virtual {method body} ;纯虚函数的定义形式:virtual { } = 0; 在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时候要求前期bind,然而虚函数却是动态绑定(run-time
bind),而且被两者修饰的函数生命周期(life recycle)也不一样。
6.如果一个类中含有纯虚函数,那么任何试图对该类进行实例化的语句都将导致错误的产生,因为抽象基类(ABC)是不能被直接调用的。必须被子类继承重载以后,根据要求调用其子类的方法。
以下为一个简单的虚函数和纯虚函数的使用演示,目的是抛砖引玉!
#include
//father class
class Virtualbase
{
public:
virtual void Demon()= 0; //prue virtual function
virtual void Base() {cout<<"this is farther class"}
};
//sub class
class SubVirtual :public Virtualbase
{
public:
void Demon() { cout<<" this is SubVirtual!"< void Base() {cout<<"this is subclass Base"}
};
/* instance class and sample */
void main()
{
Virtualbase* inst = new SubVirtual(); //multstate pointer
inst->Demon();
inst->Base();
// inst = new Virtualbase();
// inst->Base()
return ;
}
posted on 2011-10-29 14:39 Hibernate4 阅读(560) 评论(0) 编辑 收藏 举报