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.
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;
}