将从派生自std :: string的类派生的类的数据成员设置为值

时间:2016-10-27 23:37:23

标签: c++

我试图从我的二级课程中找出这个作业。 我们要创建一个名为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作为数据成员。现在,由于继承,我们应该有一个内置的数据部分(字符串)。我遇到的问题是我的所有operator =()重载现在都在所有路径上递归#34;在运行时导致stackoverflow。我将展示一个带有字符串的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;
        }
    }
}

我看到递归发生在哪里*这是调用overloaded =调用自己,因为我在=函数本身使用* this。那么将数据成员设置为提供的值的正确语法是什么呢?在它之前 - > dataMemberName =正确类型的提供值。

应该注意,我的非字符串构造函数确实设置了实例化对象的值: Double::Double(int d) : Number(to_string(d)){} 但是第二次我尝试用它们做任何事情,+ - * /,调用=函数然后再次发生错误。

3 个答案:

答案 0 :(得分:2)

只需添加:

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";
    }
};

答案 1 :(得分:1)

在评论中讨论后,我决定重写我的答案,以便更清楚我的意思。

您应该只调用基类operator=并让它处理成员分配。

您的class Number定义如下:

class Number : public string {
public:
    Number();
    Number(string set);
};

这个课程可以为我们工作,因为我们想要它没有任何修改?我们来看看。

  

我们需要的第一件事是基类中的operator=

operator=既没有声明,也没有delete在类Number中,这意味着如果你调用Number& Number::operator=(Number const&),编译器会为你生成这个函数。所以我们在这里很好。

  

对我的解决方案而言重要的第二件事是从std::string转换为Number

班级Number::Number(std::string)中有构造函数Number。幸运的是,它没有被声明为explicit,它可以隐式使用(使用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
{}

我们可以为课程operator=创建期待已久的Double

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));'时会发生什么?

  1. check_for_NaN(rhs)返回正确的字符串对象。
  2. 编译器查找Number::operator=(std::string)但找不到它。
  3. 它发现它可以生成Number::operator=(const Number&)
  4. 编译器检查它,操作员会帮忙。
  5. 如果我们可以将std::string转换为Number
  6. 但我们可以! Number::Number(std::string)构造函数不明确!
  7. 编译器生成赋值运算符。
  8. std::string rhs开始,它会创建一个类Number的临时对象。
  9. 调用生成的运算符。
  10. 我们都很高兴,因为它有效!

答案 2 :(得分:1)

您可以直接指定要使用size的{​​{1}}:

std::string