覆盖指向成员函数的指针

时间:2014-03-07 11:50:49

标签: c++ member-function-pointers

我有这两个类:

class A {
public:
    A() { m_ptr = NULL; }
    void (*m_ptr)();
    void a() { if (m_ptr) m_ptr(); }
};

class B : public A {
public:
    B() { m_ptr = b; }
    void b() {
        std::cout << "B::b() is called" << std::endl;
    }
};

我想像这样使用它们:

B b;
b.a();

并将以下内容称为B::b()

当然, 正在编译,因为B::b不属于void(*)()类型。

我怎样才能让它发挥作用?

更新。谁问“为什么?”和“为什么?” A类是一个非常基础的类,在生产代码中有许多后继者。 B级是第6个继任者,我想扩展A(最方便的地方),在那里再召唤一个方法(来自B),它可以存在,也可能不在A和B的另一个后继者中。 可以使用具有空体的虚拟方法,但它很难看,我想避免它。抽象方法更是如此(因为现有的派生后继代码) 我不想使用void(*)()类型的外部函数来放松对所有层次结构的内部数据的访问。

3 个答案:

答案 0 :(得分:2)

由于现在定义了类,因此无法使其正常工作。

调用另一个类的非静态成员函数需要该类的实例。您需要在存储函数指针时存储对拥有成员函数的对象的引用,或者在调用A::a时传递对象的引用。

您还需要使用类型m_ptr声明void (B::*)()B是指向void成员的指针,该成员不带参数并返回class A { public: A() { m_ptr = nullptr; } void a(B& b) { if (m_ptr) (b.*m_ptr)(); } // Now takes reference to B object. void (B::*m_ptr)(); // Pointer to member function of B. }; class B : public A { public: B() { m_ptr = &B::b; } // Adress of qualified function. void b() { std::cout << "B::b() is called" << std::endl; } };

看看这个例子:

B::b

现在我们可以这样调用B b; b.a(b); // Pass reference to b when calling.

class A {
public:
    virtual ~A() {}
    void a() const { b(); } // Call b.
private:
    virtual void b() const {}
};

class B : public A {
public:
    virtual void b() const override { // C++11 override specifier (optional).
        std::cout << "B::b() is called" << std::endl;
    }
};

以这种方式使用继承是令人困惑的,因为它意味着您要解决的真正问题是通过基类调用派生类的成员。这通常使用如下的简单虚函数来完成:

B b;
b.a(); // B::b is called.

并像这样使用:

{{1}}

答案 1 :(得分:1)

嗯,可能不是本练习的目的,但如果你想让它工作,你可以简单地声明static void b()

另一种选择是声明friend void b(),但"B::b() is called"打印输出会说明错误的事实。

答案 2 :(得分:0)

我建议使用CRTP,因为你想避免使用虚拟机制。但请注意,您的代码可能需要进行一些设计更改才能适应此模式。但它确实提供了类型安全性并且没有运行时开销。希望它有所帮助。

Code on ideone.com

#include <iostream>
#include <type_traits>

namespace so {

class B;

template<typename T>
class A {
 public:
  template<typename U = T, typename = typename std::enable_if<std::is_same<U, B>::value>::type>
  void foo_A() {
   std::cout << "foo_A : ";
   static_cast<U *>(this)->foo_B();
  }
};

class B: public A<B> {
 public:
  void foo_B() {
   std::cout << "foo_B" << std::endl;
  }
};

class C: public A<C> {
 public:
  void foo_C() {
   std::cout << "foo_C" << std::endl;
  }
};
} // namespace so

int main() {
 so::B b_;
 so::C c_;

 b_.foo_A();
 b_.foo_B();

 //c_.foo_A(); Compile error: A<C>::foo_A() does not exist!
 c_.foo_C();

 return (0);
}

节目输出:

foo_A : foo_B
foo_B
foo_C