0

Here's the question:

Define a class called Month that is an abstract data type for a month. Your class will have one member variable of type int to represent a month (1 for January, 2 for February, and so forth). Include all the following member functions: a constructor to set the month using the first three letters in the name of the month as three arguments, a constructor to set the month using an integer as an argument (1 for January, 2 for February, and so forth), a default constructor, an input function that reads the month as an integer, an input function that reads the month as the first three letters in the name of the month, an output function that outputs the month as an integer, an output function that outputs the month as the first three letters in the name of the month, and a member function that returns the next month as a value of type Month . Embed your class definition in a test program.

#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);
}

The code runs just fine. I try that calling constructor Month::Month (char letter1, char letter2, char letter3) from member function void Month::inputAsCh() . I can solve the problem by changing definition of Month::inputAsCh() and copy paste definitions of the constructor into the function. But, just out of curiosity, can be a constructor called from member function ? If it's okey, Month::inputAsCh() works wrong, I also try on Month test4 variable.

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
3
  • No not like you're doing. The actual instance won't be affected by a constructor call. Commented Aug 14, 2015 at 8:04
  • It's called "constructor" for a reason : you can only construct an object once. After that, the object is alive until its destruction. If you can call an object's methods, then it is already alive, so an object trying to reconstruct itself inside its method would not make sense. Commented Aug 14, 2015 at 8:27
  • The Month::Month(c1,c2,c3); in outputAsCh() is practically a NOOP. You are calling a constructor but the constructed object isnt assigned to anything, it is local to the method and thus any reasonable compiler will completely optimize it away. The other occurence (return Month(month);) is fine. Creating another month does not affect the month on which the method is called. Commented Aug 14, 2015 at 9:27

1 Answer 1

2
Month::Month(c1,c2,c3);

That line doesn't update the current object. It should be an error because Month::Month names the constructor in that context, but some compilers (notably clang) will interpret it as the construction of a temporary object instead (thanks to user657267 for the correction).

You could factor out your month calculation code into a separate function, then call that from both your constructor and your inputAsCh function:

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

Incidentally, your setMonth function could be greatly simplified by creating a std::string from those chars and comparing with that instead.

Sign up to request clarification or add additional context in comments.

23 Comments

Month::Month(c1,c2,c3); tries to call the constructor, it simply isn't valid. Month(c1,c2,c3); would construct a temporary.
I'm aware of usage string. If a constructor is called by member function, it is temporary and makes no sense ? Isn't there any way to use unlike temporary ? Should be one more function defined to do it ?
@TartanLlama It took me a while and now my brain hurts, but I think that according to [class.qual]/2 Month::Month will refer to the constructor and not the type: 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 Nice, I think you're right. I'll update the answer in a minute.
@TartanLlama - That to me is a bug in the standard, not in gcc and clang. How can you refer to something by name that the standard elsewhere says has no name?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.