Three classes: class_top->class_foo->class_bar;
The class_top creates a instance of class_foo, which will further call class_bar's method. Here is the code. I apologize it is messy, and I think that is probably why I am getting confused.
class_bar.hpp
#ifndef TWOCLASSUSEEACHOTHER_CLASS_BAR_HPP
#define TWOCLASSUSEEACHOTHER_CLASS_BAR_HPP
#include "iostream"
namespace class_bar
{
namespace class_bar_2
{
template <typename T>
class barBase
{
public:
barBase() = default;
virtual void bar_print(int n) = 0; // function later gets called to add n to m_k
void call_bar_print(int n)
{
bar_print(n);
}
private:
};
class bar : public barBase <int>
{
public:
bar() = default;
void bar_print(int n);
private:
int m_k = 1; // m_k initialized as 1
};
} // 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(int n)
{
m_k += n;
std::cout << "barBase printing m_k = " << m_k<< 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;
namespace class_foo
{
class foo
{
public:
explicit foo(double dt, bar& b, int n=5, bool flag=false);
void foo_print_from_bar(int n);
private:
bar* m_b = NULL; // member point of class foo that points to class bar
double m_dt;
int m_int;
bool m_flag;
};
}
#endif //TWOCLASSUSEEACHOTHER_CLASS_FOO_HPP
class_foo.cpp
#include "../include/class_foo.hpp"
#include "../include/class_bar.hpp"
#include <iostream>
namespace class_foo
{
foo::foo(double dt, bar& b, int n, bool flag)
: m_dt(dt),
m_b(&b)
{
m_int = n;
}
void foo::foo_print_from_bar(int n)
{
std::cout << m_dt << m_b <<m_int << m_flag;
std::cout << "foo print using ";
m_b->call_bar_print(n); // method of class barBase to do addition and pinting
}
}
class_top.hpp
#ifndef THREECLASSUSEEACHOTHER_CLASS_TOP_HPP
#define THREECLASSUSEEACHOTHER_CLASS_TOP_HPP
#include "class_bar.hpp"
#include "class_foo.hpp"
#include "vector"
using namespace class_bar::class_bar_2;
class top
{
public:
top();
void top_print(int n);
private:
class_foo::foo m_foo;
};
#endif //THREECLASSUSEEACHOTHER_CLASS_TOP_HPP
class_top.cpp
#include "../include/class_top.hpp"
using namespace class_bar::class_bar_2;
using namespace class_foo;
void top::top_print(int n)
{
bar b;
foo f(3, b);
m_foo = f; // line where problem occurs
m_foo.foo_print_from_bar(n);
}
main.cpp
#include "include/class_top.hpp"
int main()
{
top* t;
t->top_print(102); // foo calls bar to print
return 0;
}
Not all the code here is useful, so I apologize again.
The code compiled successfully, but when running it, the line throws:
Process finished with exit code 139 (interrupted by signal 11:SIGSEGV);
When I am debugging it, it seems following line is where the problem occursL
m_foo = f; // line where problem occurs
in class_top.cpp. Apparently this is not how m_foo should be used.
Trying to find how to solve this issue, so any pointer is appreciated. Some code demo would be really nice.
The root of your error is that in main()
, this code invokes Undefined Behavior at runtime:
top* t; t->top_print(102);
You are calling top_print()
on an invalid top
object via an uninitialized pointer. Which means top_print()
will try to access an m_foo
object which does not exist in memory.
Use this instead:
top t;
t.top_print(102);
That creates an actual top
object, and then calls top_print()
on it.
That being said, there are a number of other problems with your code, as well:
You should read What is the difference between #include <filename> and #include "filename"?
In class_bar.hpp
, #include "iostream"
should be #include <iostream>
instead. However, nothing in this .hpp
file directly references anything in iostream
, so you can just remove this #include
altogether. You already have the appropriate #include
in class_bar.cpp
, where it belongs.
In class_foo.hpp
, #include "stdio.h"
should be #include <stdio.h>
instead, or better #include <cstdio>
. However, you should be using nullptr
instead of NULL
, so you can just remove this #include
altogether.
In class_top.hpp
, #include "vector"
should be #include <vector>
instead. However, top
does not use std::vector
, so you can just remove this #include
altogether.
in class_bar.hpp
and class_foo.hpp
, it is not a good idea to use using namespace
statements inside of header files unless they are inside of other namespace
s. But you are using the using
statements in global scope instead. You should not pollute the global namespace.
In class_top.cpp
, you are missing a definition of the top
's constructor, which will cause an unresolved external error.
The top::m_foo
member is of type foo
, and foo
has a non-default constructor, which means top
's constructor must initialize m_foo
using its own member initialization list so it can pass parameters to m_foo
's constructor. That means top
's constructor needs access to a bar
object that outlives m_foo
, since m_foo
will be holding a pointer to that bar
object. As such, you should pass a bar&
parameter to top
's constructor so it can then pass it to foo
's constructor, eg:
class top
{
public:
top(bar& b);
void top_print(int n);
private:
class_foo::foo m_foo;
};
top::top(bar& b)
: m_foo(3, b) // <-- HERE
{
}
void top::top_print(int n)
{
m_foo.foo_print_from_bar(n);
}
Which means main()
needs a bar
object to pass to top
's constructor:
bar b; // <-- HERE
top t(b);
t.top_print(102);
the line m_foo = f;
compiles fine. Since foo
does not explicitly define a copy constructor or copy assignment operator=
for itself, the compiler will auto-generate them for you. And the default implementations will simply copy the value of all data members from one foo
object to another. In this case, the foo::m_b
member may be problematic, depending on who actually owns the bar
object. So be careful with that.
In this particular example, that is OK because the bar*
pointer is a non-owning pointer. But if it were an owning pointer, you would be in trouble unless you follow the Rule of 3/5/0 in foo
's implementation.
With all of that said, here is an online demo that addresses all of the problems mentioned above: