考虑以下两个程序。
#include <iostream>
using std::cout;
class Base {
public:
virtual void f()=0;
void g() {
f();
}
virtual ~Base() { }
};
class Derived : public Base
{
public:
void f() {
cout<<"Derived::f() is called\n";
}
~Derived() {}
};
class Derived1 : public Base
{
public:
void f() {
cout<<"Derived1::f() is called\n";
}
~Derived1() { }
};
int main() {
Derived1 d;
Base& b=d;
b.g();
b.f();
}
编译&amp;运行良好并给出预期的结果..
#include <iostream>
using std::cout;
class Base {
public:
virtual void f()=0;
Base() {
f(); // oops,error can't call from ctor & dtor
}
};
class Derived : public Base
{
public:
void f() {
std::cout<<"Derived::f() is called\n";
}
};
int main() { Derived d; Base& b=d; b.f(); }
上述程序编译失败。 为什么允许从声明纯虚函数的同一个类的成员函数中调用纯虚函数?是这样做还是未定义的行为,因为派生类仍然没有提供纯虚函数的实现?为什么不能从构造函数&amp;中调用纯虚函数?同类的析构函数?我知道Derived类构造函数可以调用基类的纯虚函数。 C ++标准对此有何看法?
答案 0 :(得分:5)
“为什么无法从构造函数中调用纯虚函数??”
因为此时最终类没有完全构造,并且vtable
未完全设置,所以正确调度函数调用。
您也可以使用static
关系建立基类和派生类,如CRTP所建议的那样:
template<class DerivedType>
class Base {
public:
void g() {
static_cast<DerivedType*>(this)->f();
}
virtual ~Base() { }
};
class Derived : public Base<Derived>
{
public:
void f() {
cout<<"Derived::f() is called\n";
}
~Derived() {}
};
class Derived1 : public Base<Derived1>
{
public:
void f() {
cout<<"Derived1::f() is called\n";
}
~Derived1() { }
};
答案 1 :(得分:1)
为什么允许从成员调用纯虚函数 声明纯虚函数的同一类的函数?
因为这在技术上是可行的并且在实践中使用:请参阅模板方法模式。
为什么不能从构造函数&amp;中调用纯虚函数? 同一类的析构函数?
这在技术上并不是直接用C ++实现的(还没有vtable)。但更重要的是,你不应该需要它,因为你在调用构造函数时总是知道对象的确切类。