#include <iostream>
using namespace std;
class Street;
class CrossStreet
{
private:
char m_chName;
Street* m_acLoS;
int m_nNoS;
static int m_nCSid;
public:
CrossStreet()
{
Init();
m_chName = m_nCSid;
}
CrossStreet(char chName)
{
Init();
m_chName = chName;
}
/** Problem is here **/
void AddStreet(Street* const cStreet)
{
m_acLoS[++m_nNoS] = cStreet;
}
~CrossStreet()
{
delete[] m_acList;
}
void Init()
{
m_nNoS = 0;
m_acLoS = 0;
m_nCSid++;
}
friend class Street;
};
class Street
{
private:
int m_nDistance;
public:
Street(CrossStreet& cHead, CrossStreet& cTail, int nDistance)
{
CreateStreet(cHead,cTail,nDistance);
}
void CreateStreet(CrossStreet& cHead, CrossStreet& cTail, int nDistance)
{
m_nDistance = nDistance;
cHead.AddStreet(Street* const THIS);
cTail.AddStreet(Street* const THIS);
}
};
当我编译上面的代码时,这个抛出错误:
-->>invalid use of incomplete 'struct Street'
-->>forward declaration of 'struct Street'
函数在'Street'对象中调用'CrossStreet'对象的AddStreet,将'THIS street对象添加到CrossStreet对象的成员变量中。所以我认为我可以在这种情况下使用THIS指针,但它不能编译。
答案 0 :(得分:3)
与this
指针无关,它与前向声明有关。您在前向声明中说Street
是class
,但它没有指定它的定义,所以在定义之前尝试使用它的定义是错误。
即使用前瞻声明:
class Street;
您可以这样说:
Street* pS
Street& rS
因为那些不需要Street的定义。但是一旦你以一种需要定义(分配Street对象)的方式使用它,你就需要完整的定义。
// m_acLoS是Street *,所以m_acLoS [...]指的是街道。 m_acLoS [++ m_nNoS] = cStreet;
看起来你真的希望数组是一个指向Street的指针数组,而不是指向Street的数组(事实上,矢量可能更好)。
但是,一般情况下,由于CrossStreet依赖于街道和街道而不依赖于CrossStreet,因此您应该将每个类的声明放在它们自己的头文件中,并将这些实现放在它们自己的.cpp文件中,这样就可以了。带有源代码的cpp文件可以在任何使用它们的代码之前#include两个完整的声明。
答案 1 :(得分:3)
没有THIS
指针这样的东西。但是有一个this
指针。因此,CreateStreet
中的代码无效(而且不仅仅是为此)。正确的语法是:
cHead.AddStreet(this); // no cast needed
AddStreet
中的问题是您已将m_acLoS
定义为指向街道的指针。因此m_acLoS[x]
的类型为Street
,而不是Street*
。但是您不能在那里使用Street
对象,因为此时您没有Street
的完整定义。您只能在CrossStreet
中使用指向街道的指针。 (此外,您缺少m_acLoS
的存储分配,因此即使您可以在那里使用该类型,并且如果分配合法,那么它仍然是一个错误。)
根据您所追求的内容,std::vector<Street*>
或std::list<Street*>
或其他一些容器可能是您正在寻找的容器,而不是那个不正确的成员数组。 (但请注意,您负责管理这些指针的生命周期。)
答案 2 :(得分:1)
有几个人已经告诉过你这个问题了。这更侧重于解决方案。我通常喜欢的是将类实现与类定义分开。我重新构造了这样的代码:
#include <iostream>
using namespace std;
class Street;
class CrossStreet {
char m_chName;
Street* m_acLoS;
int m_nNoS;
static int m_nCSid;
void Init();
public:
CrossStreet();
CrossStreet(char chName);
void AddStreet(Street* const cStreet);
~CrossStreet();
friend class Street;
};
class Street {
int m_nDistance;
public:
Street(CrossStreet& cHead, CrossStreet& cTail, int nDistance);
void CreateStreet(CrossStreet& cHead, CrossStreet& cTail, int nDistance);
};
CrossStreet::CrossStreet() {
Init();
m_chName = m_nCSid;
}
CrossStreet::CrossStreet(char chName) {
Init();
m_chName = chName;
}
void CrossStreet::AddStreet(Street* const cStreet) {
m_acLoS[++m_nNoS] = cStreet;
}
CrossStreet::~CrossStreet() {
delete[] m_acList;
}
CrossStreet::void Init() {
m_nNoS = 0;
m_acLoS = 0;
m_nCSid++;
}
Street::Street(CrossStreet& cHead, CrossStreet& cTail, int nDistance) {
CreateStreet(cHead,cTail,nDistance);
}
void Street::CreateStreet(CrossStreet& cHead, CrossStreet& cTail, int nDistance) {
m_nDistance = nDistance;
cHead.AddStreet(this);
cTail.AddStreet(this);
}
所以,这里的基本思想是类声明,然后是类定义,然后是成员函数的实现。另请注意,我已将CrossStreet::Init
设为私有,因为它显然只应由CrossStreet
的成员使用。
最后请注意,为了上帝的缘故,请为你的变量挑选一些不错的名字。您使用的唯一名称甚至是有意义和可读的中间名称m_nDistance
。 m_chName
和m_acLos
之类的内容确实非常糟糕。这些看起来很像我在编写关于匈牙利符号的邪恶的讽刺时所发明的名字,以及你可以从中得到的丑陋,难以理解的混乱。