在C++里面,虚函数的作用就是 实现 多态
构造函数可以是 虚函数,但是这样做没有多大意义,特别是在有继承关系的时候估计就不行了,没有继承关系的时候,这个类就不会被创建,编译应该是没有问题的,
析构函数 在有继承的时候,经常用虚函数,因为在 子类有实例的时候,如果让父亲的指针指向 子类的实例,而子类的实例中有new了新的地址空间,那么调用父亲的析构函数,如果父亲的析构函数不是虚的,那么只负责把父亲自己的指针回收,但是子类中new就没有回收;而如果析构函数是虚函数,那么首先是释放子类申请的地址,然后再释放父亲自己的
构造函数里面能调用 虚函数吗?
答案:肯定是可以调用的,编译是不会有问题的。
那问题是在C++中输出是怎么样的呢?例如这个虚函数在父类中有一个简单的输出,在子类中也有一个输出,那么是先调用父类的输出,再调用子类的输出,因为这个时候C++规范中了,多态此时失效,
在12.7.3条中有明确的规定。这是一种特例,在这种情况下,即在构造子类时调用父类的构造函数,而父类的构造函数中又调用了虚成员函数,这个虚成员函数即使被子类重写,也不允许发生多态的行为。即,这时必须要调用父类的虚函数,而不子类重写后的虚函数。我想这样做的原因是因为在调用父类的构造函数时,对象中属于子类部分的成员变量是肯定还没有初始化的,因为子类构造函数中的代码还没有被执行。如果这时允许多态的行为,即通过父类的构造函数调用到了子类的虚函数,而这个虚函数要访问属于子类的数据成员时就有可能出错。
总之一句话是 静态绑定 不管是::还是this->这种操作符,都是静态绑定的,没有多态
如果是在java中,都是调用子类的构造函数,输出的结果是一样的,
析构函数能调用虚函数吗?
答案:是可以调用虚函数的,但是有一点,就是不能去调用纯虚函数 这个编译是通过的,但是运行时报错
继承类在构造的时候总是首先调用其基类的构造函数来对属于其基类的部分进行构造,在这个时候,整个类被当作基类来处理,继承类的部分对整个类来说好像不存在一样,直到基类的构造函数退出并进入继承类的构造函数,该类才被当作继承类来出来处理。对析构也一样,只是析构的顺序正好相反。
构造函数实现虚函数的效果:
从形状类Shape可以派生出圆Circle、三角形Triangle、矩形Rectangle、正方形Square等等。每个类都有一个成员函数Draw,表示在屏幕上画出自己的形状。使用者使用Shape*调用Draw,那么要使画出的形状都正确,必须根据对象类型来确定使用哪个Draw来画。将Draw在Shape中定义为虚函数,并在每个派生类中重新定义该函数,那么当程序运行时,系统自动调用合适的Draw函数版本。 构造函数不能为虚函数。原因是在建立一个对象时,构造函数必须知道其确切类型,否则编译器无法进行存贮空间的分配。
要使构造函数具有虚函数的效果,通过以下方法:
例:
class Base {
public:
Base(); // 确省构造函数
Base(const Base&); // 拷贝构造函数
virtual Base* new_Obj() { return new Base();} // 具有虚构造函数效果
virtual Base* clone() { return new Base(*this);} // 具有虚构造函数效果
// ……
};
class Derived : public Base {
public:
Derived (); // 确省构造函数
Derived (const Derived&); // 拷贝构造函数
// 对基类Base中的虚函数的重定义版本
virtual Derived * new_Obj() { return new Derived();}
virtual Derived * clone() { return new Derived(*this);}
// ……
};
Base* create_Object(Base* ptr)
{
Base* p = ptr->new_Obj();
return p;
}
若ptr指向一个Base对象,则ptr->new_Obj()调用基类Base中的虚函数new_Obj建立一个动态的Base对象;若ptr指向一个Derived对象,则ptr->new_Obj()调用基类Derived中的虚函数new_Obj建立一个动态的Derived对象。