C++ C++;:从同一类的成员函数调用纯虚函数

C++ C++;:从同一类的成员函数调用纯虚函数,c++,undefined-behavior,pure-virtual,C++,Undefined Behavior,Pure Virtual,考虑以下两个程序 #include <iostream> using std::cout; class Base { public: virtual void f()=0; void g() { f(); } virtual ~Base() { } }; class Derived : public Base { public: void f() { cou

考虑以下两个程序

#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();
}
#包括
使用std::cout;
阶级基础{
公众:
虚空f()=0;
void g(){
f();
}
虚拟~Base(){}
};
派生类:公共基
{
公众:
void f(){
库特
“为什么不能从构造函数调用纯虚函数…”

因为最后一个类在这一点上没有完全构造,而且
vtable
也没有完全设置,所以无法正确地分派函数调用


您也可以为基类和派生类使用
静态
关系,例如:

模板
阶级基础{
公众:
void g(){
静态_cast(this)->f();
}
虚拟~Base(){}
};
派生类:公共基
{
公众:
void f(){
库特
为什么允许从成员调用纯虚函数
声明纯虚函数的同一类的函数

因为这在技术上是可行的,并在实践中使用:请参见模板方法模式

为什么不能从构造函数调用纯虚函数& 同一类的析构函数


<>这在C++技术上是不直接实现的(没有VTABLE)。但更基本的是,你不应该需要它,因为你在调用构造函数时总是知道对象的确切类。

相关:@vsoftco:该链接讨论了不同的主题。第二个答案解决了一些非常相似的问题,而不是相同的问题,这就是我为什么说相关。是的!这是故意的,因为基类应该是构造的首先执行。很好!我想你也可以使用
if(dynamic_cast(this))dynamic_cast(this)->f();
来确保安全,因为它会捕捉
Base*pBase=newbase;pBase->f();
,否则会给你UB。这在技术上是完全可行的,而且是不可靠的。Java就是这么做的。@T.C.编辑以考虑你的评论。
#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(); }
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() { }
};