【问题标题】:Linking functions using simple pointers使用简单指针链接函数
【发布时间】:2014-10-01 09:51:53
【问题描述】:

我正在尝试做一些我认为很简单的事情:使用指针链调用调用函数的函数(来自继承的类)。有没有更好的方法来实现这一点?另外,本着C++11 的精神,我将如何在这个例子中加入智能指针?此示例使应用程序崩溃:
这是示例代码,如果看起来有点傻,请见谅:

实际输出(崩溃!):

    almost there...

期望的输出:

    almost there...
    hello from function1

f1.h:

    #ifndef FUNCTION_1_H
    #define FUNCTION_1_H
    //f1.h (header file)

    #include <iostream>

    struct f1{

    int _a;
    f1() {}
    void function1();

    };

    #endif

f2.h:

    #ifndef FUNCTION_2_H
    #define FUNCTION_2_H
    //f2.h (header file) 


    #include "f1.h"

    struct f2 : public f1{

    int _b;
    f1* f1_ptr;
    f2() :f1(){}
    void function2();

    };

    #endif

f3.h:

    #ifndef FUNCTION_3_H
    #define FUNCTION_3_H


    #include "f2.h"

    struct f3 :public f2{

    int _c;
    f2* f2_ptr;
    f3() : f2(){}
    void function3();

    };

    #endif

CPP:

f3.cpp:

    #include "f3.h"


    void f3::function3(){

    //do stuff...
    //e.g. calculate an int Var3
    f2_ptr->function2(/*pass Var3 as argument*/);
    }

f2.cpp:

    #include "f2.h"


    void f2::function2(/*receive Var3*/){

    //do stuff with Var3
    //e.g. maybe use Var3 to calculate an int Var2

    std::cout << "almost there..." << std::endl;
    f1_ptr->function1(/*pass Var2 as argument*/);
    }

f1.cpp:

    #include "f1.h"


    void f1::function1(/*receive Var2*/){

    //take Var2 and use elsewhere
    //or continue linking to other functions
    std::cout << "hello from function1" << std::endl;
    }

main.cpp:

    int main(){

    f3* ptr3 = new f3;
    ptr3->function3();
    //delete ptr3;
    std::cin.get();
    return 0;
    }

【问题讨论】:

    标签: c++ pointers inheritance


    【解决方案1】:

    问题是在上层类中,指针f2*f1*没有被初始化,所以当你做f2_ptr-&gt;function2()时,你试图通过一个未初始化的指针访问一个成员函数,这导致了UB (未定义的行为)。您的代码基本上是这样做的:

    #include <iostream>
    
    using namespace std;
    
    struct Base
    {
        void f(){cout << "In f" << endl;}
    };
    
    struct Derived
    {
        Base* ptr;
    };
    
    int main()
    {
        Derived* foo;
        foo->ptr->f(); //cannot use foo->ptr, it is not initialized
    }
    

    所以你必须确保在f3 的构造函数中初始化f2_ptr 等等。关于智能指针,您可以使用std::unique_ptrstd::shared_ptr,语法为std::unique_ptr&lt;Foo&gt; pointer( new Foo )std::shared 也类似)。强烈建议使用它们,例如,您必须初始化它们(如果您使用了智能指针,则无法解决此问题)

    这里是如何写f3.cpp的提示:

    #include "f3.h"
    
    // define the constructor here (and just declare it in the header `f3.h`)
    f3::f3() : f2()
    {
        auto f2_ptr = std::make_shared<f2>(); 
        // and all our nightmares are over, f2_ptr is now a valid pointer
        // which will automatically release the allocated memory
        // when the reference count is zero
    }
    
    void f3::function3()
    {
        //do stuff...
        //e.g. calculate an int Var3
        f2_ptr->function2(/*pass Var3 as argument*/);
    }
    

    自从我开始这个,这里有一个完整的C++11 示例(它使用类内初始化),它使用链接并使用智能指针,它可以工作并且基本上等同于你的:

    #include <iostream>
    #include <memory>
    
    using namespace std;
    
    struct Base
    {
        void f_base()
        {
            cout << "In f_base" << endl;
        }
    };
    
    struct Derived
    {
        void f_derived()
        {
            cout << "In f_derived" << endl;
        }
        std::shared_ptr<Base> ptrBase = make_shared<Base>();
    };
    
    struct DerivedDerived
    {
        std::shared_ptr<Derived> ptrDerived = make_shared<Derived>();
    };
    
    int main()
    {
        DerivedDerived *foo = new DerivedDerived;
        foo->ptrDerived->ptrBase->f_base(); // OK now
    }
    

    PS:这可能会帮助您了解发生了什么 When does invoking a member function on a null instance result in undefined behavior?

    【讨论】:

    • 感谢vsoftco 的建议!对于智能指针的介绍。但是,我给出的示例的动机是首先调用 function2,然后在 function2 中有条件调用 function1 或调用其他一些 functionX(也许 function1 永远不会被调用),但是您的解决方案似乎创建了一个指向指针的指针,跳转直接到function1。有什么想法吗?
    • 即使它似乎只调用foo-&gt;ptrDerived-&gt;ptrBase (只是一级间接,实际上这“似乎”有效),它仍然是未定义的行为。所以每次你做pointer-&gt;call_something之类的事情时,你绝对必须确保pointer是有效的(换句话说,它不是nullptr)。如果您使用智能指针或初始化指针,您的代码是否不起作用?
    • 不,使用我的代码 - 当我在 f3() 构造函数中包含 shared_ptr 时,应用程序仍然崩溃。
    • @Chewco 我不明白为什么。您的代码与我在答案末尾发布的代码(就在这些 cmets 上方)不完全相同吗?
    • 我照原样复制/粘贴了它。我最近在使用 VC++ 2013 时遇到了重大问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多