我在一个项目里的一个B类声明中创建了A类的对象,使用A类的有参构造。被B类误认为是函数声明。此错误困扰了我很长时间,现在将错误复盘如下:
错误描述
#include <iostream>
#include <string>
using namespace std;
class classA
{
public:
classA(int i);
};
classA::classA(int i)
{
cout << i << "by classA" << endl;
}
class classB
{
public:
classB(int j);
classA a(1);
};
classB::classB(int j)
{
cout << j << "by classB" << endl;
}
int main()
{
classB b(1);//声明一个对象
system("pause");
return 0;
}
这时候,会报错:
2 IntelliSense: 应输入类型说明符 e:\WorkSpace\C&C++\Error\类内声明另一个类对象\类内声明另一个类对象\err.cpp 21 11 类内声明另一个类对象
1 error C2059: 语法错误:“常量” e:\workspace\c&c++\error\类内声明另一个类对象\类内声明另一个类对象\err.cpp 21 1 类内声明另一个类对象
错误分析
看这句话
class classB
{
...
classA a(1);
...
};
编译器把classA a(1);
当做是函数的声明。其中classA
是函数返回值,a
是函数名,而(1)
不是符合形参格式。
如果不理解可以看下面的文章
必须使用【初始化列表】初始化数据成员的情况
解决方案
方案一:使用初始化列表
#include <iostream>
#include <string>
using namespace std;
class classA
{
public:
classA(int i);
};
classA::classA(int i)
{
cout << i << "by classA" << endl;
}
class classB
{
public:
classB(int j);
classA a;
classA a1;
};
classB::classB(int j) : a(0) , a1(1)
{
cout << j << "by classB" << endl;
}
int main()
{
classB b(1);//声明一个对象
system("pause");
return 0;
}
其中
...
classB::classB(int j) : a(0) , a1(1)
...
就是使用了初始化列表的方式,个人认为是使用构造函数时在创建classB对象时,给声明的classA对象赋值
方案二:不要声明类对象,声明一个类指针
#include <iostream>
#include <string>
using namespace std;
class classA
{
public:
classA(int i);
};
classA::classA(int i)
{
cout << i << "by classA" << endl;
}
class classB
{
public:
classB(int j);
~classB();//创建析构函数,删除构造函数中new的对象
classA * a;
classA * a1;
};
classB::classB(int j)
{
a = new classA(0);
a1 = new classA(1);
cout << j << "by classB" << endl;
}
classB::~classB()
{
delete a;//删除a对象
a = NULL;//给对象指针重新指向NULL,防止野指针
delete a1;
a1 = NULL;
}
int main()
{
classB b(1);//声明一个对象
system("pause");
return 0;
}
- 千万记得要在析构函数中删除创建的对象
展望
还是不是很理解,方案一中classB
的声明中,为何可以直接classA a;
,是调用的默认构造函数吗?我猜不是,但是是什么呢?
待以后研究吧...
干活了...
写于上班中
-2022年5月13日10:23:48