Search code examples
c++c++17initialization-listdefault-initialization

How to let a variable be dependent on other variables inside a class?


What is wrong with the variable international_standard_book_number? How can I make it that it changes, whenever isbn_field_i changes?

#include <iostream>
#include <string>

class ISBN
{
private:
  unsigned int isbn_field_1 = 0;
  unsigned int isbn_field_2 = 0;
  unsigned int isbn_field_3 = 0;
  char digit_or_letter = 'a';
  std::string international_standard_book_number =
    std::to_string(isbn_field_1) + "-" + std::to_string(isbn_field_2) + "-" +
    std::to_string(isbn_field_3) + "-" + digit_or_letter;

public:
  ISBN()
  {
    isbn_field_1 = 0, isbn_field_2 = 0, isbn_field_3 = 0, digit_or_letter = 'a';
  }
  ISBN(unsigned int a, unsigned int b, unsigned int c, char d)
  {
    isbn_field_1 = a, isbn_field_2 = b, isbn_field_3 = c, digit_or_letter = d;
  }
  friend std::ostream& operator<<(std::ostream& os, ISBN const& i)
  {
    return os << i.international_standard_book_number;
  }
};

int
main()
{
  ISBN test(1, 2, 3, 'b');
  std::cout << test << "\n";
  return 0;
}

Output:

0-0-0-a

Desired output:

1-2-3-b

Edit: This question aims at something else(why, instead of how) than mine, and its answers don't help me as much as the answers from this topic.


Solution

  • What is wrong with the variable international_standard_book_number? How can I make it that it changes, whenever isbn_field_i changes?

    Generally speaking: you have to reassign it every time one component changes.

    In your particular case: change the constructor using initialization list.

    I mean... instead

    ISBN(unsigned int a, unsigned int b, unsigned int c, char d)
     {isbn_field_1=a, isbn_field_2=b, isbn_field_3=c, digit_or_letter=d;};
    

    write

    ISBN(unsigned int a, unsigned int b, unsigned int c, char d)
     : isbn_field_1{a}, isbn_field_2{b}, isbn_field_3{c}, digit_or_letter{d}
    {}
    

    Now your example code write

    1-2-3-b
    

    What changes ?

    With

    ISBN(unsigned int a, unsigned int b, unsigned int c, char d)
     {isbn_field_1=a, isbn_field_2=b, isbn_field_3=c, digit_or_letter=d;};
    

    first your fields are default initialized, so

    isbn_field_1    = 0;
    isbn_field_2    = 0;
    isbn_field_3    = 0;
    digit_or_letter = 'a';
    
    international_standard_book_number="0"+"-"+"0"+"-"+"0"+"-"+'a';
    

    then is executed the body of the constructor

    isbn_field_1    = 1;
    isbn_field_2    = 2;
    isbn_field_3    = 3;
    digit_or_letter = 'b';
    

    but international_standard_book_number remain unchanged.

    With

    ISBN(unsigned int a, unsigned int b, unsigned int c, char d)
     : isbn_field_1{a}, isbn_field_2{b}, isbn_field_3{c}, digit_or_letter{d}
    {}
    

    the initialization list initialize the fields (and substitute the default initialization)

    isbn_field_1    = 1;
    isbn_field_2    = 2;
    isbn_field_3    = 3;
    digit_or_letter = 'b';
    

    and then is executed the default initialization of international_standard_book_number but using the new values, so

    international_standard_book_number="1"+"-"+"2"+"-"+"3"+"-"+'b';