Вся суть следующей программы в том, чтобы увидеть на экране цифру 7, поскольку m_k инициализируется как 1, а затем к ней добавляется 6.
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;
}
При запуске main.cpp выскакивает ошибка:
Process finished with exit code 139 (interrupted by signal 11:SIGSEGV)
Это из-за указателя NULL
У меня вопрос: как лучше инициализировать m_b/bar, чтобы m_k инициализировалось как 1? Очевидно, я не хочу утечки памяти, так является ли умный указатель решением? Если да, то как мне его использовать? Некоторые примеры кода были бы очень признательны.
Примечание. На данный момент bar не использует foo, поэтому тривиальный ответ — делать то, что рекомендует Тед, но я сомневаюсь, что в этом случае вы задали бы этот вопрос. Один из foo или bar может напрямую содержать другой, но да, для другого нужен указатель или ссылка. Вам нужно решить, кто из двоих должен принять на себя удар, и если вы придете к выводу, что bar на самом деле не нужно foo, вы вернетесь к подходу Теда. Если нет, то мы не сможем чем-то помочь, если вы не предоставите нам дополнительную информацию об отношениях bar с foo.
@user4581301user4581301Это имеет смысл. Спасибо.





foo::m_b не указывает на действительный объект bar при вызове m_b->barBase_print(), отсюда и сбой.
Вы можете передать ссылку bar& или указатель bar* на конструктор foo для инициализации m_b, а затем main() можете создать экземпляр bar для создания f, например:
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;
}
Оно работает. Большое спасибо!
Непонятно, почему у вас указатель на
bar, а не простоbar. Если у вас есть указатель, вам нужно убедиться, что он действительно указывает на что-то, прежде чем разыменовывать его. Поскольку в вашем коде нет экземпляраbar, трудно сказать, когда назначить указатель. Если экземплярbarнедоступен при созданииfoo, вам понадобится какой-то способ присвоения указателю позже. Также не используйтеNULL(если вы используете C++11 или более позднюю версию). Используйтеnullptr.