【问题标题】:calling constructor from member function从成员函数调用构造函数
【发布时间】:2015-08-14 07:58:41
【问题描述】:

问题来了:

定义一个名为 Month 的类,它是一个月的抽象数据类型。您的类将有一个 int 类型的成员变量来表示一个月(1 代表一月,2 代表二月,依此类推)。包括以下所有成员函数:使用月份名称中的前三个字母作为三个参数设置月份的构造函数,使用整数作为参数设置月份的构造函数(1 代表一月,2 代表二月,以及以此类推),默认构造函数,将月份读取为整数的输入函数,将月份读取为月份名称中的前三个字母的输入函数,将月份输出为整数的输出函数,将月份输出为月份名称中的前三个字母的输出函数,以及将下个月作为 Month 类型的值返回的成员函数。将您的类定义嵌入到测试程序中。

#include <iostream>
using namespace std;

class Month
{
public:
    Month (char letter1, char letter2, char letter3);
    Month (int numOfMonth);
    Month ();
    void inputAsNum(); // read month as integer
    void inputAsCh(); //  read first three chars of month
    void outputAsCh() const;
    void outputAsNum() const;
    Month nextMonth();
private:
    int month;
};

int main()
{
    Month test(5);
    //test.inputAsNum();
    cout << "Current month is " << endl;
    test.outputAsCh();
    test.outputAsNum();
    cout << endl;
    test.nextMonth();
    cout << "Next month is " <<endl;
    test.outputAsCh();
    test.outputAsNum();
    cout << endl;

    Month test2('a','p','r');
    //test2.inputAsCh();
    cout << "Current month is " << endl;
    test2.outputAsCh();
    test2.outputAsNum();
    cout << endl;
    test2.nextMonth();
    cout << "Next month is " <<endl;
    test2.outputAsCh();
    test2.outputAsNum();
    cout << endl;


    Month test3;
    test3.inputAsNum();
    cout << "Current month is " << endl;
    test3.outputAsCh();
    test3.outputAsNum();
    cout << endl;
    test3.nextMonth();
    cout << "Next month is " <<endl;
    test3.outputAsCh();
    test3.outputAsNum();
    cout << endl;

    Month test4;
    test4.inputAsCh();
    cout << "Current month is " << endl;
    test4.outputAsCh();
    test4.outputAsNum();
    cout << endl;
    test4.nextMonth();
    cout << "Next month is " <<endl;
    test4.outputAsCh();
    test4.outputAsNum();
    cout << endl;

    return 0;
}

Month::Month (char letter1, char letter2, char letter3)
{
    if ((letter1 == 'j')&&(letter2 == 'a')&&(letter3 == 'n'))
        month= 1;
    else if ((letter1 == 'f')&&(letter2 == 'e')&&(letter3 == 'b'))
        month= 2;
    else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'r'))
        month= 3;
    else if ((letter1 = 'a')&&(letter2 == 'p')&&(letter3 == 'r'))
        month= 4;
    else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'y'))
        month= 5;
    else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'n'))
        month= 6;
    else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'l'))
        month= 7;
    else if ((letter1 == 'a')&&(letter2 == 'u')&&(letter3 == 'g'))
        month= 8;
    else if ((letter1 == 's')&&(letter2 == 'e')&&(letter3 == 'p'))
        month= 9;
    else if ((letter1 == 'o')&&(letter2 == 'c')&&(letter3 == 't'))
        month= 10;
    else if ((letter1 == 'n')&&(letter2 == 'o')&&(letter3 == 'v'))
        month= 11;
    else if ((letter1 == 'd')&&(letter2 == 'e')&&(letter3 == 'c'))
        month= 12;
}
Month::Month (int numOfMonth)
                    :month(numOfMonth)
{ }
Month::Month ()
                    :month(1)
{ }
void Month::inputAsNum()
{
    int num;
    cout << "Enter num of month => ";
    cin  >> num;
    month = num;
}
void Month::inputAsCh()
{
    char c1,c2,c3;
    cout << "Enter three letters of month => ";
    cin  >> c1 >> c2 >> c3;
    Month::Month(c1,c2,c3);
}
void Month::outputAsCh() const
{
    if (month == 1)
        cout << "Jan ";
    else if (month == 2)
        cout << "Feb ";
    else if (month == 3)
        cout << "Mar ";
    else if (month == 4)
        cout << "Apr ";
    else if (month == 5)
        cout << "May ";
    else if (month == 6)
        cout << "Jun ";
    else if (month == 7)
        cout << "Jul ";
    else if (month == 8)
        cout << "Aug ";
    else if (month == 9)
        cout << "Sep ";
    else if (month == 10)
        cout << "Oct ";
    else if (month == 11)
        cout << "Nov ";
    else if (month == 12)
        cout << "Dec ";
}
void Month::outputAsNum() const
{
    cout << month;
}
Month Month::nextMonth()
{
    if (month < 12)
        month++;
    else if (month == 12)
        month = 1;
    return Month(month);
}

代码运行良好。我尝试从成员函数 void Month::inputAsCh() 调用构造函数 Month::Month (char letter1, char letter2, char letter3) 。我可以通过更改Month::inputAsCh() 的定义并将构造函数的粘贴定义复制到函数中来解决问题。但是,出于好奇,可以从成员函数调用构造函数吗?如果没问题,Month::inputAsCh() 会出错,我也试试Month test4 变量。

Output                                  Expected Output
-------------                           -----------------
Current month is                        Current month is 
Nov 11                                  Nov 11
Next month is                           Next month is 
Dec 12                                  Dec 12
Current month is                        Current month is 
Apr 4                                   Apr 4
Next month is                           Next month is 
May 5                                   May 5
Enter num of month => 2                 Enter num of month => 2
Current month is                        Current month is 
Feb 2                                   Feb 2
Next month is                           Next month is 
Mar 3                                   Mar 3
Enter three letters of month => apr     Enter three letters of month => apr
Current month is                        Current month is 
Jan 1                                   Apr 4
Next month is                           Next month is 
Feb 2                                   May 5

【问题讨论】:

  • 不,不像你正在做的。实际实例不会受到构造函数调用的影响。
  • 它被称为“构造函数”是有原因的:你只能构造一个对象一次。在那之后,该对象是活着的,直到它被破坏。如果你可以调用一个对象的方法,那么它已经是活着的,所以一个对象试图在它的方法中重建自己是没有意义的。
  • Month::Month(c1,c2,c3); 中的 outputAsCh() 实际上是一个 NOOP。您正在调用构造函数,但构造的对象没有分配给任何东西,它是方法的本地对象,因此任何合理的编译器都会完全优化它。另一种情况(return Month(month);)很好。创建另一个月份不会影响调用该方法的月份。

标签: c++ class constructor


【解决方案1】:
Month::Month(c1,c2,c3);

该行不会更新当前对象。这应该是一个错误,因为Month::Month 在该上下文中命名了构造函数,但一些编译器(尤其是 clang)会将其解释为临时对象的构造(感谢 user657267 的更正)。

您可以将月份计算代码分解为一个单独的函数,然后从您的构造函数和 inputAsCh 函数中调用它:

void setMonth(char letter1, char letter2, char letter3)
{
    if ((letter1 == 'j')&&(letter2 == 'a')&&(letter3 == 'n'))
        month= 1;
    else if ((letter1 == 'f')&&(letter2 == 'e')&&(letter3 == 'b'))
        month= 2;
    else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'r'))
        month= 3;
    else if ((letter1 = 'a')&&(letter2 == 'p')&&(letter3 == 'r'))
        month= 4;
    else if ((letter1 == 'm')&&(letter2 == 'a')&&(letter3 == 'y'))
        month= 5;
    else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'n'))
        month= 6;
    else if ((letter1 == 'j')&&(letter2 == 'u')&&(letter3 == 'l'))
        month= 7;
    else if ((letter1 == 'a')&&(letter2 == 'u')&&(letter3 == 'g'))
        month= 8;
    else if ((letter1 == 's')&&(letter2 == 'e')&&(letter3 == 'p'))
        month= 9;
    else if ((letter1 == 'o')&&(letter2 == 'c')&&(letter3 == 't'))
        month= 10;
    else if ((letter1 == 'n')&&(letter2 == 'o')&&(letter3 == 'v'))
        month= 11;
    else if ((letter1 == 'd')&&(letter2 == 'e')&&(letter3 == 'c'))
        month= 12;
}

Month::Month (char letter1, char letter2, char letter3)
{
    setMonth(letter1, letter2, letter3);
}

void Month::inputAsCh()
{
    char c1,c2,c3;
    cout << "Enter three letters of month => ";
    cin  >> c1 >> c2 >> c3;
    setMonth(c1,c2,c3);
}

顺便说一句,您的setMonth 函数可以通过从那些chars 创建一个std::string 并与之进行比较来大大简化。

【讨论】:

  • Month::Month(c1,c2,c3); 尝试调用构造函数,它根本无效。 Month(c1,c2,c3); 将构建一个临时的。
  • 我知道使用字符串。如果构造函数被成员函数调用,它是临时的并且没有意义?有没有什么方法可以使用不像临时的?是否应该再定义一个函数来做到这一点?
  • @TartanLlama 我花了一段时间,现在我的脑痛,但我认为根据 [class.qual]/2 Month::Month 将引用构造函数和不是类型:In a lookup in which function names are not ignored33 and the nested-name-specifier nominates a class C: [...] if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C [...] the name is instead considered to name the constructor of class C.
  • @user657267 很好,我认为你是对的。我会在一分钟内更新答案。
  • @TartanLlama - 这对我来说是标准中的错误,而不是 gcc 和 clang。你怎么能用名字来引用其他地方的标准说没有名字的东西呢?
猜你喜欢
  • 2011-03-06
  • 2018-05-13
  • 2011-12-07
  • 1970-01-01
  • 2017-09-07
  • 2012-09-28
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多