c++classpointersreference

Good practice to initiate class member pointer that points to another class?


The whole point of the following program is to see 7 printed on the screen, because m_k is initialized as 1, and then 6 is added to it.

class_bar.hpp

#ifndef TWOCLASSUSEEACHOTHER_CLASS_BAR_HPP
#define TWOCLASSUSEEACHOTHER_CLASS_BAR_HPP

#include "iostream"

namespace class_bar
{
namespace class_bar_2
{

class foo;

template <typename T>
class barBase
{
public:
    barBase() = default;
    void barBase_print(int n) // function later gets called to add n to m_k
    {
        m_k += n;
        std::cout << "barBase printing m_k = " << m_k<< std::endl;
    }
private:
    int m_k = 1; // m_k initialized as 1
};

class bar : public barBase <int>
{
public:
    bar() = default;
    void bar_print();

private:

};

}   // class_bar_2
}   // bar

#endif //TWOCLASSUSEEACHOTHER_CLASS_BAR_HPP

class_bar.cpp

#include "../include/class_bar.hpp"
#include <iostream>

namespace class_bar
{
namespace class_bar_2
{

void bar::bar_print()
{
    std::cout << "bar printing" << std::endl;
}

}   // class_bar2
}   // class_bar

class_foo.hpp

#ifndef TWOCLASSUSEEACHOTHER_CLASS_FOO_HPP
#define TWOCLASSUSEEACHOTHER_CLASS_FOO_HPP    
#include "stdio.h"

// forward declaration
namespace class_bar
{
namespace class_bar_2
{
class bar;
}
}

using namespace class_bar::class_bar_2;

// class foo
namespace class_foo
{

class foo
{
public:
    foo() = default;
    void foo_print_from_bar();

private:
    bar* m_b = NULL; // member point of class foo that points to class bar
};
}

#endif //TWOCLASSUSEEACHOTHER_CLASS_FOO_HPP

class_foo.cpp

#include "../include/class_foo.hpp"
#include "../include/class_bar.hpp"

#include <iostream>

namespace class_foo
{
void foo::foo_print_from_bar()
{
    std::cout << "foo print using ";
    m_b->barBase_print(6); // method of class barBase to do addition and pinting
}
}

main.cpp

#include <iostream>
#include "include/class_foo.hpp"
#include "include/class_bar.hpp"

int main()
{
    class_foo::foo f;

    f.foo_print_from_bar(); // foo calls bar to print

    std::cout << "Hello, World!" << std::endl;
    return 0;
}

When running main.cpp, error pops:

Process finished with exit code 139 (interrupted by signal 11:SIGSEGV)

This is because of the NULL pointer

My questions is, what is a good practice to initialize m_b/bar, so that m_k is initialized as 1? Obviously I don't want any memory leak, so is smart pointer a solution? If so how do I use it? Some code samples would be really appreciated.


Solution

  • foo::m_b is not pointing at a valid bar object when you call m_b->barBase_print(), hence the crash.

    You can pass a bar& reference or bar* pointer to foo's constructor to initialize m_b, and then main() can create a bar instance to construct f with, eg:

    class foo
    {
    public:
        foo(bar& b); // or: foo(bar* b);
        void foo_print_from_bar();
    
    private:
        bar* m_b = NULL; // member point of class foo that points to class bar
    };
    
    foo::foo(bar& b) : m_b(&b) {}
    // or:
    // foo::foo(bar* b) : m_b(b) {}
    
    void foo::foo_print_from_bar()
    {
        std::cout << "foo print using ";
        m_b->barBase_print(6); // method of class barBase to do addition and pinting
    }
    
    int main()
    {
        class_bar::class_bar_2::bar b;
        class_foo::foo f(b); // or: foo f(&b);
    
        f.foo_print_from_bar(); // foo calls bar to print
    
        std::cout << "Hello, World!" << std::endl;
        return 0;
    }