Abstract declarator used as declaration

Hi, I'm trying to study for my second test tomorrow and I'm just doing out of the book programming challenges, I can't get my code to run because I'm getting the error in the title. It's at the end of my header file, I also have a ton other errors.
The challenge is to "design a class called date. The class should store a date w/ 3 integers : month, day , year. and 3 print functions "12/25/2018"
"December 25, 2018", "25 December 2018" Don't accept day greater than 31 or less than 1, no months greater than 12 or less than 1"
I realize some people have already done this code. but I was trying to do a fresh start at it, and borrowed from my own previous class programs, and it's very broken. I tried to google "abstract declarator" but I can't find my issue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//#pragma once
#ifndef Date
#define Date
#include <iostream>
#include <string>
using namespace std;

const int MAX_MONTH = 12;
const int MAX_DAY = 31;

    class Date
    {
     /*private:
        int top;
        int bottom;
        int wholeNumber;
        void Simplify(); */
    public:
        FirstDate(int month, int day, int year);
        int month;
        int day;
        int year;
       // string monthName;
        void setNames(int month, string monthName);
        void PrintNumDate(int month, int day, int year);
        void PrintMonthFirst();
        void PrintDayFirst();
        void setMonth(int month);
        void setDay(int day);
        void setYear(int year);
    };  //first error is on this line <<<<<<<<<<<<<<<<<<<<<<
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "Date.h"
#include <string>
#include <iomanip>
using namespace std;
{
    Date::FirstDate()
    {
        int month = 1;
        int day = 1;
        int year = 1;
        string monthName = "January";
    }
    void Date::setNames(int month, string monthName)
    {
        switch(month)
        {
            case '1' : monthName = "January";
                break;
            case '2' : monthName = "February"
                break;
            case '3' : monthName = "March";
                break;
            case '4' : monthName = "April";
                break;
            case '5' : monthName = "May";
                break;
            case '6' : monthName = "June";
                break;
            case '7' : monthName = "July";
                break;
            case '8' : monthName = "August";
                break;
            case '9' : monthName = "September";
                break;
            case '10' : monthName = "October";
                break;
            case '11' : monthName = "November";
                break;
            case '12' : monthName = "December";
                break;
        }
    }


    void Date::PrintNumDate(int month, int day, int year)
    {
        cout << month << "/" << day << "/" << year;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "Date.h"
#include <iostream>

using namespace CurrentDate;
using namespace std;


int main()
{
    Date::Date();
    cout << "Hello world!" << endl;
    PrintNumDate(int month, int day, int year);

    return 0;
}
Ok I found a lot of my errors, not sure what fixed the first one. But a lot of just simple format was wrong.
Now I get an error in my Main program at the end "Date.PrintNumDate();" "expected unqualified ID before '.' token"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#pragma once
//#ifndef Date
//#define Date
#include <iostream>
#include <string>
using namespace std;

const int MAX_MONTH = 12;
const int MAX_DAY = 31;

class Date {
public:
    Date();
    NewDate(int, int, int);
    int month;
    int day;
    int year;
   // string monthName;
    void setNames(int month, string monthName);
    void PrintNumDate(int month, int day, int year);
    void PrintMonthFirst();
    void PrintDayFirst();
    void setMonth(int month);
    void setDay(int day);
    void setYear(int year);

};

//#endif
// implementation file <<<<<<<<<<<<<<<<<<<<<
#include "Date.h"
#include <string>
#include <iomanip>
using namespace std;

Date::Date()
{
    int month = 1;
    int day = 1;
    int year = 1;
    string monthName = "January";
}

Date::NewDate(int month, int day, int year)
{
    month = month;
    day = day;
    year = year;
    // use set date function here
}

void Date::setNames(int month, string monthName)
{
    switch(month)
    {
        case '1' : monthName = "January";
            break;
        case '2' : monthName = "February";
            break;
        case '3' : monthName = "March";
            break;
        case '4' : monthName = "April";
            break;
        case '5' : monthName = "May";
            break;
        case '6' : monthName = "June";
            break;
        case '7' : monthName = "July";
            break;
        case '8' : monthName = "August";
            break;
        case '9' : monthName = "September";
            break;
        case '10' : monthName = "October";
            break;
        case '11' : monthName = "November";
            break;
        case '12' : monthName = "December";
            break;
    }
}

    void Date::PrintNumDate(int month, int day, int year)
    {
        cout << month << "/" << day << "/" << year;
    }
// Main file <<<<<<<<<<<<<<<<<<<<<<<<<<<
#include "Date.h"
#include <iomanip>
#include <iostream>

using namespace std;


int main()
{
    int month, day, year = 1;
    Date();
    cout << "Hello world!" << endl;
    cout << "Pleaser enter a month: ";
    cin >> month;
    cout << "Enter a day: ";
    cin >> day;
    cout << "Enter a year: ";
    cin >> year;

    Date.PrintNumDate();

    return 0;
}
When you get a long list of errors you should always start with the first one in the list. Later errors might not be real errors but might just be side effects of earlier errors. After fixing the first error you recompile and repeat until you have no errors.

___ http://cplusplus.com/forum/general/283271/#msg1226230 ___

When I compile the code in your first post with GCC I get the following error as the first:
1
2
3
4
5
6
class Date
{
...
    FirstDate(int month, int day, int year); // error: ISO C++ forbids declaration of ‘FirstDate’ with no type
...
};

The problem here is that the constructor is not named the same as the class. So the compiler probably thinks you are trying to define a normal member function and therefore complains when it doesn't see a type name in front of the function name.

After fixing this error I get another error:
1
2
3
4
5
6
7
8
9
10
#ifndef Date
#define Date

class Date
{
...
    Date(int month, int day, int year); // error: expected unqualified-id before ‘int’
...
};
#endif 

which to me didn't make a lot of sense at first. But then I notice your include guard is named Date, the same name as your class. This will not work. You have to name it something unique that is not used in the rest of your program. A relativity common convention is to spell the file name in upper case letters and replace dots with underscore so Date.h becomes DATE_H.
1
2
3
4
#ifndef DATE_H
#define DATE_H
...
#endif 

After making this change the code in the header compiles without errors.


___ http://cplusplus.com/forum/general/283271/#msg1226231 ___

After the earlier fixes the code in your second post only shows me the following error:
1
2
3
using namespace std;
{ // error: expected unqualified-id before ‘{’ token
...

This { should just not be there. After removing it a few more errors pop up:

Same problem as earlier with incorrectly named constructor:
1
2
3
4
Date::FirstDate() // error: ISO C++ forbids declaration of ‘FirstDate’ with no type
{
...
}

Missing semicolon:
1
2
3
4
5
6
7
8
9
10
11
12
13
void Date::setNames(int month, string monthName)
{
    switch(month)
    {
        case '1' : monthName = "January";
            break;
        case '2' : monthName = "February" // error: expected ‘;’ before ‘break’
            break;
        case '3' : monthName = "March";
            break;
        ...
    }
}


After fixing these issues I get the following error:
1
2
3
4
Date::Date() // error: no declaration matches ‘Date::Date()’
{
...
}

The problem here is that in the header you have declared the constructor to take three ints as argument but here you are defining it to take no arguments at all. You either have to change the declaration or definition so that they match, or add both constructors.

Note that this is not correct:
1
2
3
4
5
6
7
Date::Date()
{
    int month = 1;
    int day = 1;
    int year = 1;
    string monthName = "January";
}

You are declaring local variables that goes out of scope when the constructor ends. This will not affect the member variables with the same name.

Simply remove the type names
1
2
3
4
5
6
7
Date::Date()
{
    month = 1;
    day = 1;
    year = 1;
    monthName = "January";
}

or use the constructor initialization list
1
2
3
4
5
6
7
Date::Date()
:   month(1),
    day(1),
    year(1),
    monthName("January")
{
}

But for this to work you need to actually declare monthName as a member variable (maybe you want to consider if you really need both month and monthName).

There are also some warnings about "multi-character character constant" comming from '10', '11' and '12'. Note that single quotes are normally used for characters (char). Putting multiple characters between single quotes means something different but it's still not what you want. '1' is not equal to 1. So just remove the single quotes around the numbers!


___ http://cplusplus.com/forum/general/283271/#msg1226232 ___

The third post:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "Date.h"
#include <iostream>

using namespace CurrentDate; // Where is CurrentDate declared?
using namespace std;

int main()
{
    Date::Date(); // This is not how you create a variable (object).
    cout << "Hello world!" << endl;
    PrintNumDate(int month, int day, int year); // This is not how you call a member function.

    return 0;
}

The code should probably look more like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "Date.h"
#include <iostream>

using namespace std;

int main()
{
    Date date(4, 22, 2022); // Assuming you have a Date constructor that takes three ints as argument.
    cout << "Hello world!" << endl;
    date.PrintNumDate(); // For this to work you would need to change the Date::PrintNumDate() member 
                         // function so that it doesn't take any arguments and instead prints the day, 
                         // month and year of the date object that it's called on.
    
    return 0;
}

Last edited on
ok thanks, I had a { bracket after namespace because I was trying to use a custom namespace, but just got rid of it, and I think I had a left over bracket.

On the Date constructor I am trying to set an initial date to 1 for all, and January for the string
And I took out the arguments for PrintNumDate, now it's only giving me an error on the last line before return 0; it says "expected unqualified id before '.' token. Not sure how to fix that.

Thanks I didn't know my #ifndef Date can't be named the same as my class name.
What's the code for that line?
It's my main.cpp, Oh, I got it now. I think it's because I hadn't made an instance in main for it. Now I just need to finish making a set date function for any new dates, because the print is only showing 1/1/1 which it should since the constructor did that.
*side question, my book says OOP didn't start coming around until 1990, I thought that couldn't be true, but started looking into it and it seems right. Does that mean older code, that was just procedural, was easier to reverse engineer?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "Date.h"
#include <iomanip>
#include <iostream>

using namespace std;

int main()
{
    int month, day, year = 1;
  //Date();
    Date date;
    cout << "Pleaser enter a month: ";
    cin >> month;
    cout << "Enter a day: ";
    cin >> day;
    cout << "Enter a year: ";
    cin >> year;

    date.PrintNumDate();

    return 0;
}
Last edited on
jetm0t0 wrote:
Does that mean older code, that was just procedural, was easier to reverse engineer?

Not sure exactly what you mean by "reverse engineer" in this context.

OOP in C++ doesn't add any protection against hackers and that sort of thing. The access specifiers (private, protected and public) are there to prevent friendly programmers that respect the rules from making mistakes. Without access specifiers you might use naming conventions or comments to show that a member variable is not supposed to be accessed from "outside" but that is easier to miss and some people might be tempted to ignore it because it "seems to work".
Last edited on
Oh ok, I just meant that when other people use the program they take it a apart and learn how it works. IDK like the typical movie interpretation of reverse engineering, but I guess I realize now, if anyone has any source code there is no guesses involved, they can simply read it. Maybe the code should be encrypted for security. But in general the programs of the past were probably much less complicated?
A class compiles down to the same thing as a struct. The member variables are stored the same way in memory, etc.

1
2
3
4
5
6
struct Date
{
        int month;
        int day;
        int year;
};

1
2
3
4
5
6
7
8
9
class Date
{
public: 
        /* lots of member functions */
private:
        int month;
        int day;
        int year;
};

The way instances of this struct and class are stored in memory is typically the same. sizeof(Date) is usually 12 bytes in both cases (assuming sizeof(int) is 4).
Last edited on
Topic archived. No new replies allowed.