Хорошая практика инициировать указатель члена класса, указывающий на другой класс?

Вся суть следующей программы в том, чтобы увидеть на экране цифру 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, а не просто bar. Если у вас есть указатель, вам нужно убедиться, что он действительно указывает на что-то, прежде чем разыменовывать его. Поскольку в вашем коде нет экземпляра bar, трудно сказать, когда назначить указатель. Если экземпляр bar недоступен при создании foo, вам понадобится какой-то способ присвоения указателю позже. Также не используйте NULL (если вы используете C++11 или более позднюю версию). Используйте nullptr.

Ted Lyngmo 20.08.2024 22:23

Примечание. На данный момент bar не использует foo, поэтому тривиальный ответ — делать то, что рекомендует Тед, но я сомневаюсь, что в этом случае вы задали бы этот вопрос. Один из foo или bar может напрямую содержать другой, но да, для другого нужен указатель или ссылка. Вам нужно решить, кто из двоих должен принять на себя удар, и если вы придете к выводу, что bar на самом деле не нужно foo, вы вернетесь к подходу Теда. Если нет, то мы не сможем чем-то помочь, если вы не предоставите нам дополнительную информацию об отношениях bar с foo.

user4581301 20.08.2024 23:00

@user4581301user4581301Это имеет смысл. Спасибо.

Nick X Tsui 21.08.2024 15:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Оно работает. Большое спасибо!

Nick X Tsui 21.08.2024 02:42

Другие вопросы по теме