如何让一个变量依赖于class中的其他变量?
How to let a variable be dependent on other variables inside a class?
变量international_standard_book_number
有什么问题?每当 isbn_field_i
发生变化时,我怎样才能让它发生变化?
#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;
}
输出:
0-0-0-a
期望的输出:
1-2-3-b
编辑:This question 的目标不是我的(为什么,而不是如何),它的答案对我的帮助不如这个主题的答案。
使用成员函数。
#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() const {
return 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;
}
C++ 中的变量使用值语义。当你这样做时
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;
它会根据 isbn_field_n
现在的值给 international_standard_book_number
赋值。它不会在这些变量之间创建某种自动 link 以确保它们保持同步。
如果您想要这种行为,则必须确保每次更新其他字段时都更新 international_standard_book_number
。
What is wrong with the variable international_standard_book_number
? How can I make it that it changes, whenever isbn_field_i
changes?
一般来说:每改变一个组件就得重新赋值。
在您的特定情况下:使用初始化列表更改构造函数。
我的意思是...相反
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;};
写入
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}
{}
现在你的示例代码写
1-2-3-b
有什么变化?
有
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;};
首先你的字段是默认初始化的,所以
isbn_field_1 = 0;
isbn_field_2 = 0;
isbn_field_3 = 0;
digit_or_letter = 'a';
international_standard_book_number="0"+"-"+"0"+"-"+"0"+"-"+'a';
然后执行构造函数体
isbn_field_1 = 1;
isbn_field_2 = 2;
isbn_field_3 = 3;
digit_or_letter = 'b';
但international_standard_book_number
保持不变。
有
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}
{}
初始化列表初始化字段(并替代默认初始化)
isbn_field_1 = 1;
isbn_field_2 = 2;
isbn_field_3 = 3;
digit_or_letter = 'b';
然后执行 international_standard_book_number
的默认初始化,但使用新值,所以
international_standard_book_number="1"+"-"+"2"+"-"+"3"+"-"+'b';
如果您只需要设置一次值(例如其他值在对象后不会改变
构造)你可以使用初始化列表:
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),
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)
{};
但请记住,成员仍然按照声明的顺序进行初始化,而不是按照初始化列表的顺序进行初始化。
从技术上讲,您不需要在初始化列表中初始化international_standard_book_number
,正如max66的答案所示,这是个人喜好问题。
维护class 不变量(取决于变量)这是你必须手动编码的。这是我们需要 classes 的原因之一。在 class 中,您可以禁止直接更改成员(将它们设为私有),但是当它们通过例如特殊设置方法更改时,相应地更新不变量。
例如
void set_field_1(int field) {
isbn_field_1 = field;
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;
}
我想添加到 。
通常你有一个相互调用的构造函数层次结构和一个最终的 final "master" 构造函数,它接受所有参数并初始化变量。这避免了代码重复并极大地简化了哪些构造函数初始化了什么。您可以在下面的示例中看到我的意思。除此之外,要以可读的方式进行适当的字符串格式化,请使用 {fmt} 库:
#include <fmt/format.h>
#include <string>
class ISBN
{
private:
unsigned int isbn_field_1;
unsigned int isbn_field_2;
unsigned int isbn_field_3;
char digit_or_letter;
std::string international_standard_book_number;
public:
ISBN()
: ISBN{ 0, 0, 0, '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 }
, international_standard_book_number{ fmt::format("{}-{}-{}-{}",
isbn_field_1,
isbn_field_2,
isbn_field_3,
digit_or_letter) }
{}
};
此代码在 Visual Studio 2019 年至少有效:
#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(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), 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)
{
}
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";
test = {2, 3, 4, 'c'};
std::cout << test << "\n";
return 0;
}
此外,为什么构造函数为空?
变量international_standard_book_number
有什么问题?每当 isbn_field_i
发生变化时,我怎样才能让它发生变化?
#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;
}
输出:
0-0-0-a
期望的输出:
1-2-3-b
编辑:This question 的目标不是我的(为什么,而不是如何),它的答案对我的帮助不如这个主题的答案。
使用成员函数。
#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() const {
return 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;
}
C++ 中的变量使用值语义。当你这样做时
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;
它会根据 isbn_field_n
现在的值给 international_standard_book_number
赋值。它不会在这些变量之间创建某种自动 link 以确保它们保持同步。
如果您想要这种行为,则必须确保每次更新其他字段时都更新 international_standard_book_number
。
What is wrong with the variable
international_standard_book_number
? How can I make it that it changes, wheneverisbn_field_i
changes?
一般来说:每改变一个组件就得重新赋值。
在您的特定情况下:使用初始化列表更改构造函数。
我的意思是...相反
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;};
写入
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}
{}
现在你的示例代码写
1-2-3-b
有什么变化?
有
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;};
首先你的字段是默认初始化的,所以
isbn_field_1 = 0;
isbn_field_2 = 0;
isbn_field_3 = 0;
digit_or_letter = 'a';
international_standard_book_number="0"+"-"+"0"+"-"+"0"+"-"+'a';
然后执行构造函数体
isbn_field_1 = 1;
isbn_field_2 = 2;
isbn_field_3 = 3;
digit_or_letter = 'b';
但international_standard_book_number
保持不变。
有
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}
{}
初始化列表初始化字段(并替代默认初始化)
isbn_field_1 = 1;
isbn_field_2 = 2;
isbn_field_3 = 3;
digit_or_letter = 'b';
然后执行 international_standard_book_number
的默认初始化,但使用新值,所以
international_standard_book_number="1"+"-"+"2"+"-"+"3"+"-"+'b';
如果您只需要设置一次值(例如其他值在对象后不会改变 构造)你可以使用初始化列表:
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),
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)
{};
但请记住,成员仍然按照声明的顺序进行初始化,而不是按照初始化列表的顺序进行初始化。
从技术上讲,您不需要在初始化列表中初始化international_standard_book_number
,正如max66的答案所示,这是个人喜好问题。
维护class 不变量(取决于变量)这是你必须手动编码的。这是我们需要 classes 的原因之一。在 class 中,您可以禁止直接更改成员(将它们设为私有),但是当它们通过例如特殊设置方法更改时,相应地更新不变量。
例如
void set_field_1(int field) {
isbn_field_1 = field;
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;
}
我想添加到
通常你有一个相互调用的构造函数层次结构和一个最终的 final "master" 构造函数,它接受所有参数并初始化变量。这避免了代码重复并极大地简化了哪些构造函数初始化了什么。您可以在下面的示例中看到我的意思。除此之外,要以可读的方式进行适当的字符串格式化,请使用 {fmt} 库:
#include <fmt/format.h>
#include <string>
class ISBN
{
private:
unsigned int isbn_field_1;
unsigned int isbn_field_2;
unsigned int isbn_field_3;
char digit_or_letter;
std::string international_standard_book_number;
public:
ISBN()
: ISBN{ 0, 0, 0, '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 }
, international_standard_book_number{ fmt::format("{}-{}-{}-{}",
isbn_field_1,
isbn_field_2,
isbn_field_3,
digit_or_letter) }
{}
};
此代码在 Visual Studio 2019 年至少有效:
#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(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), 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)
{
}
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";
test = {2, 3, 4, 'c'};
std::cout << test << "\n";
return 0;
}
此外,为什么构造函数为空?