Как переслать объявить функцию-член класса для использования в другом классе?
Я сделал два одинаковых класса X и Y, указав друг на друга. См. Код ниже для X.h, Y.h идентичен всем X и Y, замененным. Этот код дает, однако, ошибку в моем методе Connect (ошибка C2027: использование undefined типа "Y" ). В X.h у меня есть forward, объявленный классом Y, но он не знает, что Y имеет метод с именем SetXPointer. Поэтому мне также нужно переслать декларировать этот метод, исправить?
Если я попытаюсь это сделать (добавив строку Y:: SetXPointer (X * pX_in); в классе строк Y;), я получаю ошибку компилятора C2761: 'void Y:: SetXPointer (X *)': не разрешено повторное использование функции члена. Есть ли способ использовать общедоступный метод класса Y в классе X?
// 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;
};
Ответы
Ответ 1
Не включать тело метода в тело класса. Напишите оба класса, и после того, как оба класса будут заполнены, напишите варианты реализации метода:
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
будут одинаковыми, так же, как и производительность.
Единственным недостатком является то, что вы не сможете разделить эти два класса на два заголовка разумным способом.
Ответ 2
Единственный способ сделать это, если оба класса нуждаются в полном типе в своих методах, заключается в том, чтобы разделить реализацию на файл реализации.
Ответ 3
Если вы намерены совместно использовать большие части реализации между 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
.
Ответ 4
Вы можете поместить класс 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;
}