【问题标题】:passing function as constructor parameter to base class constructor while initializing在初始化时将函数作为构造函数参数传递给基类构造函数
【发布时间】:2016-12-02 12:03:27
【问题描述】:
#include <iostream>
#include<cstdio>
#include<typeinfo>

using std::cout;
using std::endl;

class foo;
class bar
{
    public:
        bar()
        {
        }
        bar(void (*getNextValue)(void)):memberFunctionPointer(getNextValue)
        {
        }
        void calltoderivedslass()
        {
            //  *memberFunctionPointer();
            ((bar*)this)->bar::memberFunctionPointer;
        }
        void (foo::*memberFunctionPointer)();
};

class foo : public bar
{
    public:
        foo( ):bar(static_cast<foo::*memberFunctionPointer>(&foo::hello))
        {
        }
        void hello()
        {
            printf("Hello \n\n");
        }
};
void byebye()
{
    cout << "bye" << endl;
}
int main()
{
    foo testfoo;
    //((testfoo).*(testfoo.memberFunctionPointer))();
    return 0;
}

错误:

classname.cpp: In constructor "bar::bar(void (*)())":
classname.cpp:15:68: error: cannot convert "void (*)()" to "void (foo::*)()" in initialization
classname.cpp: In constructor "foo::foo()":
classname.cpp:29:25: error: expected type-specifier
classname.cpp:29:25: error: expected ">"
classname.cpp:29:25: error: expected "("
classname.cpp:29:30: error: expected unqualified-id before "*" token
classname.cpp:31:2: error: expected "{" at end of input

期望:

我要初始化基类函数指针,初始化它指向派生类成员函数。我想在创建派生类的对象时初始化它。从基类我想使用获取的函数指针调用派生类函数。

提前感谢大家。

【问题讨论】:

  • 如果您正确使用 OOP,则无需使用函数指针...考虑一下必须维护您的代码的程序员..
  • 是的,需要使用函数指针。当数据库读取发生错误时,必须调用回调,所以我需要函数指针,不要给代码维护带来困难。谢谢:)

标签: c++ class constructor callback function-pointers


【解决方案1】:

在我看来像虚拟方法:

class bar
{
    public:
        bar()
        {
        }
        void calltoderivedslass()
        {
            this->hello();
        }
        virtual void hello() = 0;
};

class foo : public bar
{
    public:
        foo( )
        {
        }
        void hello() override
        {
            printf("Hello \n\n");
        }
};

另一种方法可能是使用好奇循环模板模式 (CRTP) 来实现静态多态性:

template<typename T>
class bar
{
    public:
        bar()
        {
        }
        void calltoderivedslass()
        {
            static_cast<T*>(this)->hello();
        }
};

class foo : public bar<foo>
{
    public:
        foo( )
        {
        }
        void hello()
        {
            printf("Hello \n\n");
        }
};

如果你真的想保留指向成员函数的指针,你可以考虑将std::function绑定到this

class bar
{
    public:
        bar()
        {
        }
        template<typename F>
        bar(F&& getNextValue):memberFunctionPointer(std::forward<F>(getNextValue))
        {
        }
        void calltoderivedslass()
        {
            this->memberFunctionPointer();
        }
        std::function<void()> memberFunctionPointer;
};

class foo : public bar
{
    public:
        foo( ):bar(std::bind(&foo::hello, this))
        {
        }
        void hello()
        {
            printf("Hello \n\n");
        }
};

我猜是扩展用法:

void byebye()
{
    cout << "bye" << endl;
}
int main()
{
    bar testbar(byebye);
    testbar.calltoderivedslass(); // not a derived class, but it works
    return 0;
}

【讨论】:

  • 感谢您的回答,当我使用您的代码时,出现如下错误,
  • @KiruthikaPalanivelu 没有“如下错误”^^ 无论如何,你添加#include &lt;functional&gt; 使用std::function 吗?
  • 感谢您的回答,当我使用您的代码时,我收到如下错误,错误:预期â,â或â...â之前â&&â令牌错误:命名空间âstd中的âfunctionâ确实not name a type In constructor âbar::bar(F)â: error: class âbarâ does not have any field named âmemberFunctionPointerâ error: âforwardâ is not a member ofâstdâ error: expected primary-expression beforeâ>â token error:âgetNextValueâ was未在此范围内声明在成员函数中“void bar::calltoderivedslass()”:错误:“class bar”没有名为“memberFunctionPointer”的成员
  • @KiruthikaPalanivelu 您是否包含functional?你用的是什么编译器?我的代码需要 C++11 支持
  • 线程模型:posix gcc 版本 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 是的!!当我使用它时,我的编译终止了。 kiru4.cpp: 在构造函数 âfoo::foo()â: kiru4.cpp:29:20: error: âbindâ is not a member of âstdâ
【解决方案2】:

bar 的构造函数错误。

构造函数bar(void (*getNextValue)(void)) 不期望foo 函数的成员函数指针,因此无法使用getNextValue 类型初始化bar::memberFunctionPointer

您需要将构造函数中的参数更改为void (foo::*getNextValue)(void)才能编译。

但整体设计对我来说似乎并不正确......所以我认为@wasthishelpful 的答案更有帮助;-)

【讨论】:

  • 该错误已修复:) 但仍然出现此错误 classname.cpp: In constructor âfoo::foo()â: classname.cpp:29:25: error: expected type-specifier classname.cpp: 29:25:错误:预期â>â classname.cpp:29:25:错误:预期â(â classname.cpp:29:30:错误:预期â*â token classname.cpp:31:2之前的unqualified-id : 错误: 预期 â{â 在输入结束
  • Simon-kraemer 这是我的派生类构造函数,我正在尝试将函数指针传递给基类构造函数 foo():bar(static_cast<:>(&foo::hello))如果我错了,请纠正我。
  • 是的,但是接收方隐式地将成员函数转换回来。顺便说一句:你不需要在 foo. &amp;foo::hello 已经是正确的类型。看看这个:godbolt.org/g/Bw72R1 请检查另一个答案,因为它绝对是更好的解决方案!
  • 再次感谢-Simon Kraemer。编译错误已修复。但我没有得到我想要的输出。 testfoo.calltoderivedslass();我希望我的派生类函数 hello() 被调用,但这没有发生。这种语法有什么问题吗, ((bar*)this)->bar::memberFunctionPointer;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2014-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多