我已经制作了两个相同的类X和Y,并且指向了彼此。有关X.h的信息,请参阅下面的代码,Y.h与所有X和Y的互换完全相同。但是,此代码在我的方法Connect中出错(错误C2027:使用未定义类型'Y')。在X.h中,我已经向前声明了类Y,但它不知道Y有一个名为SetXPointer的方法。因此我还需要转发声明这个方法,对吗?
如果我尝试这样做(添加行Y :: SetXPointer(X * pX_in);在行类Y;下),我得到编译器错误C2761:'void Y :: SetXPointer(X *)':成员函数重新声明不允许。有没有办法在类X中使用类Y的公共方法?
// X.h
#pragma once
#include "Y.h"
// Forward declaration
class Y;
class X
{
public:
X(void) : data(24) {};
~X(void) {};
int GetData() { return data; }
void SetYPointer(Y* pY_in) { pY = pY_in; }
Y* GetYPointer() { return pY; }
void Connect(Y* Y_in) { pY = Y_in; Y_in->SetXPointer(this); }
private:
int data;
Y *pY;
};
答案 0 :(得分:14)
不要在类体中包含方法体。编写这两个类,在两个类完成后,编写方法实现:
class Y;
class X {
…
void Connect(Y* Y_in);
…
};
class Y {
…
void Connect(X* X_in);
…
};
inline void X::Connect(Y* Y_in) {
pY = Y_in;
Y_in->SetXPointer(this);
}
inline void Y::Connect(X* X_in) {
pX = X_in;
X_in->SetXPointer(this);
}
这样,在实现Connect
方法时,可以获得有关如何将类对象放在内存中的完整信息。并且作为类体中的方法和声明为inline
的方法都将以相同的方式内联,性能也将是相同的。
唯一的缺点是你无法以合理的方式将这两个类分成两个标题。
答案 1 :(得分:3)
如果您的类在其方法中都需要完整类型,那么执行此操作的唯一方法是将实现与实现文件分开。
答案 2 :(得分:2)
如果您打算在X和Y之间共享大部分实现,您可能希望使用模板来实现。一个例子如下:
template<bool isX> class XY
{
public:
typedef XY<!isX> YX; // This is the opposite type to the current one.
XY(void) : data(24) {};
~XY(void) {};
int GetData() { return data; }
void SetPointer(YX* pYX_in) { pYX = pYX_in; }
YX* GetPointer() { return pYX; }
void Connect(YX* YX_in) { pYX = YX_in; YX_in->SetPointer(this); }
private:
int data;
YX *pYX;
};
typedef XY<true> X;
typedef XY<false> Y;
由于模板方法仅在使用时进行实例化,因此可以避免上述问题,因为在实例化时,两种类型都是已知的。如果您稍后在X
和Y
之间存在差异,则可以使用继承而不是typedef
。
答案 3 :(得分:2)
您可以将B级放入A级
using namespace std;
class A
{
public:
void run()
{
B b("hi");
b.run(this);
}
void print(string &msg) { cout << msg << endl; }
private:
class B
{
public:
B(string m) : msg(m) {}
void run(A *a) { a->print(msg); }
private:
string msg;
};
};
int main()
{
A a;
a.run();
return 0;
}