【问题标题】:C++: call pure virtual function from member function of same classC ++:从同一类的成员函数调用纯虚函数
【发布时间】:2015-08-05 14:18:40
【问题描述】:

考虑以下 2 个程序。

#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();
}

编译和运行良好并给出预期的结果..

#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(); }

上述程序编译失败。 为什么允许从声明纯虚函数的同一个类的成员函数中调用纯虚函数?这样做很好还是因为派生类仍然不提供纯虚函数的实现而导致未定义的行为?为什么不能从同一个类的构造函数和析构函数中调用纯虚函数?我知道派生类构造函数可以调用基类的纯虚函数。 C++ 标准对此有何规定?

【问题讨论】:

  • @vsoftco:该链接讨论了不同的主题。
  • 第二个答案解决的问题非常相似,不一样,这就是我说相关的原因。

标签: c++ undefined-behavior pure-virtual


【解决方案1】:

“为什么不能从构造函数调用纯虚函数...?”

因为此时最终类尚未完全构建,并且 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() { }
};

【讨论】:

  • 是的!而且是故意的,因为基类应该先构建。
  • 不错!我认为你也可以使用if(dynamic_cast&lt;DerivedType*&gt;(this)) dynamic_cast&lt;DerivedType*&gt;(this)-&gt;f(); 来保证安全,因为它会捕获Base&lt;Derived&gt;* pBase = new Base&lt;Derived&gt;; pBase-&gt;f();,否则会给你 UB。
【解决方案2】:

为什么允许从成员调用纯虚函数 声明纯虚函数的同一个类的函数?

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

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

从技术上讲,这在 C++ 中实现起来并不简单(还没有 vtable)。但更根本的是,无论如何你都不应该需要它,因为在调用构造函数时你总是知道对象的确切类。

【讨论】:

  • 这在技术上是相当可行的——而且被打破了。这就是 Java 所做的。
  • @T.C.编辑以考虑您的评论。
猜你喜欢
  • 2013-06-29
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
相关资源
最近更新 更多