编辑:阅读粗体行以找到我遇到问题的地方。看了答案改了代码还是报错
我是 C++ 的新手,我正在测试一些东西以了解如何使用该语言,我遇到了这种情况:
我有一个 struct
,它创建一个指向另一个 struct
的指针。另一个 struct
反过来创建一个指向首先实例化它的 struct
的指针。
这是一个简单的例子,可以更好地解释我的意思(这部分已经更改,添加了代码,粗体行是我遇到问题的地方):
#include <string>
using namespace std;
struct Month;
struct Year;
struct Day{
unsigned int day, dayNumber;
string name;
Day(){}
void setDayNumber(unsigned int dayNumber){
this -> dayNumber = dayNumber;
switch(dayNumber){
case 0:
name = "Sunday";
break;
case 1:
name = "Monday";
break;
case 2:
name = "Tuesday";
break;
case 3:
name = "Wednesday";
break;
case 4:
name = "Thursday";
break;
case 5:
name = "Friday";
break;
case 6:
name = "Saturday";
break;
}
}
};
struct Month{
string name;
unsigned int monthLength, monthNumber;
Month *previousMonth, *nextMonth;
Year *year;
Day *days;
Month(unsigned int monthNumber, Year *year){
this -> monthNumber = monthNumber;
switch(monthNumber){
case 0:
name = "January";
break;
case 1:
name = "February";
break;
case 2:
name = "March";
break;
case 3:
name = "April";
break;
case 4:
name = "May";
break;
case 5:
name = "June";
break;
case 6:
name = "July";
break;
case 7:
name = "August";
break;
case 8:
name = "September";
break;
case 9:
name = "October";
break;
case 10:
name = "November";
break;
case 11:
name = "December";
break;
}
previousMonth = NULL;
nextMonth = NULL;
this -> year = year;
}
void createDays(){
if(name == "January" || name == "March" || name == "May" || name == "July" || name == "August" || name == "October" || name == "December")
monthLength = 31;
else if(name != "February")
monthLength = 30;
else{
**if(year -> isLeapYear() == true)** //This line is problematic, see below the code to see what the compiler says
monthLength = 29;
else
monthLength = 28;
}
days = new Day[monthLength];
for(unsigned int i = 0; i < monthLength; i++){
days[i].day = i+1;
if(i == 0 && previousMonth == NULL)
days[i].setDayNumber(2);
else if(i == 0)
days[i].setDayNumber(previousMonth -> days[previousMonth -> monthLength - 1].dayNumber);
else
days[i].setDayNumber(days[i-1].dayNumber);
}
}
};
struct Year{
unsigned int year;
Year *previousYear, *nextYear;
Month *months;
Year(unsigned int year){
this -> year = year;
previousYear = NULL;
nextYear = NULL;
}
void createMonths(){
Month *currentMonth = months;
unsigned int monthNumber;
for(unsigned int i = 0; i < 12; i++){
months = new Month(i, this);
}
while(currentMonth != NULL){
monthNumber = currentMonth -> monthNumber;
if(monthNumber == 0 && previousYear != NULL){
months[monthNumber].previousMonth = &(previousYear -> months[11]);
months[monthNumber].nextMonth = &(months[monthNumber+1]);
}
else if(monthNumber == 11 && nextYear != NULL){
months[monthNumber].nextMonth = &(nextYear -> months[0]);
months[monthNumber].previousMonth = &(months[monthNumber-1]);
}
else{
if(monthNumber != 0)
months[monthNumber].previousMonth = &(months[monthNumber-1]);
if(monthNumber != 11)
months[monthNumber].nextMonth = &(months[monthNumber+1]);
}
}
currentMonth = months;
while(currentMonth != NULL){
currentMonth -> createDays();
currentMonth = currentMonth -> nextMonth;
}
}
bool isLeapYear(){
if(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
return true;
else
return false;
}
};
编译器输出的信息如下:
pe_019.cpp(107): error C2027: use of undefined type 'Year'
pe_019.cpp(10) : see declaration of 'Year'
pe_019.cpp(107): error C2227: left of '->isLeapYear' must point to class/struct/union/generic type
显然,还有更多,但在 Year
中,我使用了一个 struct Month
数组,在 Month
中,有指向其父 Year
的指针。 (与 Day
相同,具有父级 Month
)。
当我尝试编译时,编译器说我正在使用未定义的 struct 'Month'
,Month*
的大小未知,等等。
我很确定这是因为在声明之前使用了 Month
,但我不能先声明它,因为 Year
将是未声明的 结构
。
正确的做法是什么?
编辑:在阅读了这个问题的答案后,我提前声明了 Year 并将 Month 放在 Year 之前,但是由于我没有包含在原始帖子中的功能,我仍然遇到问题因为我认为这不是问题的一部分,所以我编辑了我的代码以使其更完整。
最佳答案
可以通过以下几种方式改进您的代码。
#include <string>
using std::string;
struct Year;
struct Day;
struct Month{
string name;
unsigned int monthLength;
struct Month *previousMonth, *nextMonth;
struct Year *year;
struct Day *days;
};
struct Year{
unsigned int year;
struct Year *previousYear, *nextYear;
struct Month months[12];
};
这个修复的最重要的问题是,尽管 Month 的定义只指定了一个指向 Year 的指针,Year 的定义> 实际上包括整个月。让我们考虑一下,因为这里有一些重要的东西需要学习。如果编译器还不知道 Month 是什么,它如何决定如何在内存中布置 Year?回答:它不能,因为它甚至不知道 Month 的大小。
仅仅包含一个指针不会带来这个问题,因为编译器知道指针的大小,即使它不知道所指向对象的类型。
您的代码还需要一些分号,以及一个标准的 header 包含,这两者都是我添加的。
祝你好运。
更新以响应下面 OP 的评论: 修改后的代码发布在下面。请注意,它以及如何延迟受影响函数的定义,直到函数所需的类型被完全定义为止。
(顺便说一句,如果您对我的想法感兴趣,使用命名空间 std 几乎从不推荐。它破坏了 C++ 有用的命名空间机制。)
#include <string>
using namespace std;
struct Month;
struct Year;
struct Day{
unsigned int day, dayNumber;
string name;
Day(){}
void setDayNumber(unsigned int dayNumber){
this -> dayNumber = dayNumber;
switch(dayNumber){
case 0:
name = "Sunday";
break;
case 1:
name = "Monday";
break;
case 2:
name = "Tuesday";
break;
case 3:
name = "Wednesday";
break;
case 4:
name = "Thursday";
break;
case 5:
name = "Friday";
break;
case 6:
name = "Saturday";
break;
}
}
};
struct Month{
string name;
unsigned int monthLength, monthNumber;
Month *previousMonth, *nextMonth;
Year *year;
Day *days;
Month(unsigned int monthNumber, Year *year){
this -> monthNumber = monthNumber;
switch(monthNumber){
case 0:
name = "January";
break;
case 1:
name = "February";
break;
case 2:
name = "March";
break;
case 3:
name = "April";
break;
case 4:
name = "May";
break;
case 5:
name = "June";
break;
case 6:
name = "July";
break;
case 7:
name = "August";
break;
case 8:
name = "September";
break;
case 9:
name = "October";
break;
case 10:
name = "November";
break;
case 11:
name = "December";
break;
}
previousMonth = NULL;
nextMonth = NULL;
this -> year = year;
}
void createDays();
};
struct Year{
unsigned int year;
Year *previousYear, *nextYear;
Month *months;
Year(unsigned int year){
this -> year = year;
previousYear = NULL;
nextYear = NULL;
}
void createMonths(){
Month *currentMonth = months;
unsigned int monthNumber;
for(unsigned int i = 0; i < 12; i++){
months = new Month(i, this);
}
while(currentMonth != NULL){
monthNumber = currentMonth -> monthNumber;
if(monthNumber == 0 && previousYear != NULL){
months[monthNumber].previousMonth = &(previousYear -> months[11]);
months[monthNumber].nextMonth = &(months[monthNumber+1]);
}
else if(monthNumber == 11 && nextYear != NULL){
months[monthNumber].nextMonth = &(nextYear -> months[0]);
months[monthNumber].previousMonth = &(months[monthNumber-1]);
}
else{
if(monthNumber != 0)
months[monthNumber].previousMonth = &(months[monthNumber-1]);
if(monthNumber != 11)
months[monthNumber].nextMonth = &(months[monthNumber+1]);
}
}
currentMonth = months;
while(currentMonth != NULL){
currentMonth -> createDays();
currentMonth = currentMonth -> nextMonth;
}
}
bool isLeapYear(){
if(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
return true;
else
return false;
}
};
void Month::createDays(){
if(name == "January" || name == "March" || name == "May" || name == "July" || name == "August" || name == "October" || name == "December")
monthLength = 31;
else if(name != "February")
monthLength = 30;
else{
if(year -> isLeapYear() == true)
monthLength = 29;
else
monthLength = 28;
}
days = new Day[monthLength];
for(unsigned int i = 0; i < monthLength; i++){
days[i].day = i+1;
if(i == 0 && previousMonth == NULL)
days[i].setDayNumber(2);
else if(i == 0)
days[i].setDayNumber(previousMonth -> days[previousMonth -> monthLength - 1].dayNumber);
else
days[i].setDayNumber(days[i-1].dayNumber);
}
}
关于c++ - 在结构中引用另一个结构,其中第二个结构也引用第一个结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9892484/