Изменение структуры или класса внутри класса | с указателями или без - PullRequest
0 голосов
/ 09 мая 2018

Изменение значений классов / структур внутри классов для меня загадка. Сегодня я попытался провести некоторое исследование и нашел следующее решение. Интересно, это правильный способ для функции изменить вещи внутри класса? Есть ли необходимость, чтобы это как-то было сделано с помощью указателей? Есть ли более правильный способ сделать это?

#include <iostream>

int main()
{

class Someclass {
    private:
    int Integer;

    public:

    Someclass(int i):
    Integer(i){} //CTOR

    struct Somestruct { 
        int a, b;
    };
    Somestruct Mystruct;

    void func(){
        Mystruct.a = Integer/2;
        Mystruct.b = Integer*2;
    };
};

Someclass A(10);
A.func();
std::cout << A.Mystruct.a << " " << A.Mystruct.b << std::endl;
} 

Причина, по которой я пишу этот код, заключается в том, что я хочу проанализировать файл, начиная со строки "Integer", в заданную пользователем структуру "Mystruct", которую этот класс должен каким-то образом доставить мне. Это приемлемый способ написания такого кода?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Я понимаю, что ваш вопрос касается инкапсуляции, так как следует понимать, что внутренняя структура является держателем данных, и внешний класс должен каким-то образом управлять этим.

Слабые стороны вашего дизайна

В вашем дизайне Mystruct публично. Таким образом, все, что находится вне Someclass, может получить доступ к данным, но также и изменить их. Это подвержено ошибкам, так как нет гарантии, что внешний код не нарушает некоторый инвариант структуры.

Пути улучшения

Самым чистым было бы, конечно, сделать несколько методов получения и установки для доступа к данным. Но с 30 участниками, это много кода.

Если ваш процесс построения инициализирует данные struture, вторым подходом может быть ограничение внешнего доступа только для чтения. Вы бы сделали это, сделав Mystruct закрытым и предложив функцию, возвращающую константную ссылку:

class Someclass {
    Somestruct Mystruct; 
public: 
    ...
    const Somestruct& get() { return Mystruct; }
};

std::cout << A.get().a << " " << A.get().b << std::endl;

Демоверсия

Тем не менее, прежде чем идти в этом направлении, я бы проверил, нельзя ли инкапсулировать доступ к необработанным данным структуры, например, предоставляя функции, которые управляют данными без необходимости знать внутренние компоненты:

class Somestruct {
    ...
public:
    ostream& show_simplified_specs(ostream& os) {
        os << a << " " << b;
    }
}

Третий подход может заключаться в использовании шаблона проектирования строителя для инкапсуляции процесса построения Someclass на основе Somestruct и других частей.

Указатели?

По возможности следует избегать указателей. Например, предположим, что у вас есть вектор Someclass для хранения всех этих классов в памяти. В данный момент вы получаете указатель на элемент Mystruct. Предположим, что вы добавите новый элемент в вектор: все предыдущие указатели могут стать недействительными.

Этот же риск потенциально может существовать со ссылками. Но я думаю, что, хотя это обычная идиома для кэширования указателя, возвращаемого функцией, на практике менее распространенным и привлекательным является копирование ссылки, возвращаемой функцией.

0 голосов
/ 09 мая 2018

Это то, что вы ищете? Я не очень уверен, что правильно вас понял.

template <int I>
struct Someclass;

template <>
struct Someclass<1>
{
    int Integer = 1;
    int a, b;

    void func()
    {
        a = Integer/2;
        b = Integer*2;
    }
};

template <>
struct Someclass<2>
{
    int Integer = 2;
    int a, b, c;

    void func()
    {
        a = Integer/2;
        b = Integer*2;
        c = Integer*Integer;
    }
};

int main()
{
    Someclass<1> A;
    A.func();
    std::cout << A.a << " " << A.b << std::endl;

    Someclass<2> B;
    B.func();
    std::cout << B.a << " " << B.b << " " << B.c << std::endl;

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...