Вся суть следующей программы в том, чтобы увидеть на экране цифру 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
.