0

I have this class:

class model
{
private:
    link_list list;
    float parameter_B1;
    float parameter_B0;
public:
    model();
    float getparameter_B1() const;
    float getparameter_B0() const;
    float predict();
    void info();
};

In which float parameter_B1 and float parameter_B0 are constant , but in order to initialize them , I have to enter constructor body and read a file and using that file's data to find value of these two attributes, but once I set them ,they won't change again.(so I guess they are count as constant)

like this:

model::model()
{
    char filename[300];
    cout << "enter file name(path\\filname.txt):" << endl;
    cin >> filename;
    FILE* fp;
    fp = fopen(filename, "r+");
    float x, y;
    if (fp == NULL)
    {
        cout << "Unable to open the file!" << endl;
        exit(EXIT_FAILURE);
    }
    else
    {
        while (!feof(fp))
        {
            if (fscanf(fp, "%f\t%f", &x, &y) == 2)
            {
                Pair p(x, y);
                list.insertNewNode(p);
            }
        }
    }
    Pair _average = list.average();
    parameter_B1 = list.parameters1(_average);
    parameter_B0 = list.parameters2(_average, parameter_B1);
}

but if I change my class to:

class model
{
private:
    link_list list;
    const float parameter_B1;
    const float parameter_B0;
public:
    model();
    const float getparameter_B1() const;
    const float getparameter_B0() const;
    float predict();
    void info();
};

I will receive these error "model::model()" provides no initialize for:

1. const member "model::parameter_B1"

2. const member "model::parameter_B0"

, but as you can see I can't use initializer list.

what should I do? is not declaring constant variable my only solution?

hanie
  • 1,863
  • 3
  • 9
  • 19
  • 1
    You can't assign to `const` variables, but you can *initialize* them, In your case you can't initialize them either, since the values of the variables depend on external run.-time factors. – Some programmer dude Apr 18 '20 at 09:41
  • 1
    Factory pattern comes to my mind. You could read the file in another function/class and provide the parameters as arguments to `model` constructor. – Yksisarvinen Apr 18 '20 at 09:41
  • 2
    On another couple of unrelated notes, first of all please don't do much in a constructor. A constructor should initialize member variables to a reasonable default state, not more. If you want to read from a file then create a function to be called after construction. Also please don't use old C-style I/O (`fopen` and friends). And lastly please read [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Some programmer dude Apr 18 '20 at 09:42
  • 3
    Returning `const float` is useless BTW. – Jarod42 Apr 18 '20 at 09:43
  • Since they are private, why do you care? No user of the class can change the variables because you don't provide any mechanism to do so, so just document that they are effectively constants, and leave it at that. – john Apr 18 '20 at 09:43
  • @Yksisarvinen yeah you are right ,that would solve this problem , but I have to read this file in model constructor.(question requires this) – hanie Apr 18 '20 at 09:44
  • Whereas const members give some meaning, it also forbid some operation which might be legit as copy assignment. – Jarod42 Apr 18 '20 at 09:45
  • Delegating constructor might help (depending of the wording of the requirement). – Jarod42 Apr 18 '20 at 09:47
  • @Someprogrammerdude I wouldn't normally do this in my constructor ,but the question forced me to read file in my constructor. – hanie Apr 18 '20 at 09:48
  • Hmm. How about an immutable class for storing those parameters? So that you have a struct `params`, which has only const members, but the object of this struct in `model` is non-const. If you were to modify the params, you have to exchange the whole object. However, at this point john's suggestion seems better. – Yksisarvinen Apr 18 '20 at 09:52

1 Answers1

0

with delegating constructor, you might do

std::tuple<link_list, float, float> read_model_file()
{
    char filename[300];
    cout << "enter file name(path\\filname.txt):" << endl;
    cin >> filename;
    // ...
    Pair _average = list.average();
    parameter_B1 = list.parameters1(_average);
    parameter_B0 = list.parameters2(_average, parameter_B1);
    return {std::move(list), parameter_B0, parameter_B1};
}

class model
{
private:
    link_list list;
    const float parameter_B0;
    const float parameter_B1;
public:
    model() : model(read_model_file()) {}
    model(std::tuple<link_list, float, float> t) :
        list(std::get<0>(std::move(t))),
        parameter_B0(std::get<1>(std::move(t))),
        parameter_B1(std::get<2>(std::move(t)))
    {}
    // ...
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302