我有这两个类:
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(*)()类型的外部函数来放松对所有层次结构的内部数据的访问。
答案 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,因为你想避免使用虚拟机制。但请注意,您的代码可能需要进行一些设计更改才能适应此模式。但它确实提供了类型安全性并且没有运行时开销。希望它有所帮助。
#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