将从std::string派生的类派生的类的数据成员设置为值
Setting the data member for a class derived from a class derived from std::string to a value
我正试图从我的2级课程中找出这个作业。我们将创建一个名为Number的类,它派生自std::string。这个类中唯一的代码是两个构造函数,一个是默认构造函数,另一个是将字符串作为参数的构造函数。我有:
class Number : public string {
public:
Number();
Number(string set);
}
然后将构造函数编码为:
Number::Number() : string("0") { } // default constructor sets data string to "0"
Number::Number(string set) : string(set) { }
到目前为止还不错。然后我们要取两个我们一直在开发的类,Double和Integer,并从Number派生它们。在这两个类中,我们曾经分别有一个double和一个int作为数据成员。现在,由于继承,我们应该有一个内置的数据段(字符串(。我遇到的问题是,我的所有运算符=((重载现在都是"在所有路径上递归的",导致运行时出现堆栈溢出。我将展示一个Double构造函数的例子,它使用字符串,以及导致无限递归的equals函数。
Double::Double(string d) : Number(d)
{
// overloaded constructor that takes a string argument
if (isNaN(d)) {
*this = "0.0";
}
else {
*this = d;
}
// used for setting the value of a data member with a string
void Double::operator=(string d)
{
if (isNaN(d)) {
*this = "0.0";
}
else {
*this = d;
}
}
}
我看到递归发生在哪里,因为*this正在调用重载的=,它调用自己,因为我在=函数本身中使用*this。那么,将数据成员设置为提供的值的正确语法是什么呢。以前只是这个->dataMemberName=提供了正确类型的值。
需要注意的是,我的非字符串构造函数确实设置了实例化对象的值:Double::Double(int d) : Number(to_string(d)){}
但当我尝试对它们执行任何操作时,+-*/,=函数被调用,然后错误再次发生。
只需添加:
using std::string::operator=;
缩写示例:
#include <string>
class Number : public std::string {
public:
};
class Double : public Number {
public:
using std::string::operator=;
Double()
{
*this="0.0";
}
};
在评论中讨论后,我决定重写我的答案,以便更清楚地理解我的意思。
您应该只调用基类operator=
并让它处理成员分配。
class Number
定义如下:
class Number : public string {
public:
Number();
Number(string set);
};
这门课能按照我们的要求在不做任何修改的情况下为我们工作吗?让我们看看。
我们首先需要的是基类中的
operator=
。
operator=
既没有声明,Number
类中也没有delete
d,这意味着如果您调用Number& Number::operator=(Number const&)
,编译器将为您生成此函数。所以我们在这里很好。
对于我的解决方案来说,第二件重要的事情是从
std::string
到Number
的转换。
类Number
中存在构造函数Number::Number(std::string)
。幸运的是,它没有声明为explicit
-co,它可以隐式使用(使用explicit
构造函数会更详细,但也是可能的(。编译器将在需要将std::string
转换为Number
时使用此构造函数。单参数构造函数有时被称为转换构造函数。好的,所以我们已经满足了第二个要求。
这就是我们所需要的基础课!
现在开始工作。
我们从创建一个辅助函数开始:
std::string check_for_NaN(std::string s)
{
if(isNaN(s)) { return "0.0"; }
return s;
}
现在我们可以简化Double
的构造函数:
Double::Double(std::string s): Number(check_for_NaN(s)) //no magic here
{}
我们可以为类Double
:创建期待已久的operator=
Double& operator=(std::string rhs)
{
Number::operator=(check_for_NaN(rhs)); //here we have magic, explained below
//if Double has some members of its own, copy them here
return *this;
}
那么,当我们调用'Number::operator=(check_for_NaN(rhs((;'时会发生什么呢?
check_for_NaN(rhs)
向我们返回正确的字符串对象- 编译器查找
Number::operator=(std::string)
,但找不到它 - 发现它可以生成
Number::operator=(const Number&)
- 编译器检查它,这样的运算符会有所帮助
- 如果我们能把CCD_ 23转换成CCD_
- 但我们可以!有一个
Number::Number(std::string)
构造函数不是显式的 - 编译器生成赋值运算符
- 它从
std::string rhs
创建一个类为Number
的临时对象 - 调用生成的运算符
- 我们都很高兴,因为它成功了
您可以直接指定要使用std::string
的operator=
:
#include <string>
using namespace std;
class Number : public string
{
public:
Number();
Number(string set);
};
Number::Number() : string("0") {}//default constructor sets data string to "0"
Number::Number(string set) : string(set) {}
class Double : public Number {
public:
//using Number::operator=;
Double(string d);
void operator=(string d);
double val;
};
bool isNaN(string d) { return false; }
Double::Double(string d) : Number(d) {//overloaded constructor that takes a string argument
if(isNaN(d))
{
string::operator=("0.0");
}
else
{
string::operator=(d);
}
}
void Double::operator=(string d)//used for setting the value of a data member with a string
{
if(isNaN(d))
{
string::operator=("0.0");
}
else
{
string::operator=(d);
}
}
int main()
{
Double d("3");
d = "4";
return 0;
}
- std::用派生类对象设置,但用gcc8.1设置基类比较器
- 无法在 qt 中为 QWidget 中的派生类设置样式表
- 如何使用基类对象设置派生类变量的值
- 在基类和派生类之间正确设置函数的返回
- 设置一系列基/派生类来处理天气数据
- 由派生类设置的 constexpr 基类成员
- 在C 中,如何将派生类中的私有变量设置为基类的输入值
- 当我在基类中设置受保护的数据时,它会更改派生类中受保护数据的值
- C++派生类的设置属性到从同一基类派生的未知类对象
- 适用于具有常见属性但值不同的派生类的设计设置
- 如何设置通知功能,以便在创建QWidget派生对象时触发
- C++-填充派生类数据成员,同时设置基类属性值
- 如何设置仅对派生于不同类的类可见的方法
- 通过将基类强制转换为派生类并设置数据来扩展基类
- C++:如何强制派生类来设置基成员变量
- 如何通过派生类的方法复制来设置基类字段
- 如何使用包含不同typedef枚举的派生类模板设置构造函数初始化列表
- 抽象类成员无法访问派生类中设置的值
- 是推荐使用下转换的做法来设置派生类成员变量
- 通过转换基类指针来设置派生类字段