C++ 如何转发声明一个类的成员函数以在另一个类中使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11344195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:03:03  来源:igfitidea点击:

How to forward declare a member function of a class to use in another class?

c++forward-declaration

提问by physicalattraction

I have made two identical classes X and Y, with a pointer to each other. See the code below for X.h, Y.h is identical with all X's and Y's interchanged. This code gives however an error in my method Connect (error C2027: use of undefined type 'Y'). In X.h, I have forward declared the class Y, but it doesn't know that Y has a method named SetXPointer. Therefore I also need to forward declare this method, correct?

我创建了两个相同的类 X 和 Y,并带有一个相互指向的指针。Xh 的代码参见下面的代码,Yh 与所有 X 和 Y 互换时相同。然而,这段代码在我的方法 Connect 中给出了一个错误(错误 C2027:使用未定义的类型“Y”)。在 Xh 中,我已经向前声明了类 Y,但它不知道 Y 有一个名为 SetXPointer 的方法。因此我也需要转发声明这个方法,对吗?

If I try to do this (adding the line Y::SetXPointer(X* pX_in); under the line class Y;), I get a compiler error C2761: 'void Y::SetXPointer(X *)' : member function redeclaration not allowed. Is there a way to use a public method of class Y in class X?

如果我尝试这样做(在行类 Y 下添加行 Y::SetXPointer(X* pX_in);),我会收到编译器错误 C2761: 'void Y::SetXPointer(X *)' : member function redeclaration不允许。有没有办法在 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;
};

回答by MvG

Don't include the method body in the class body. Write both classes, and after both classes are complete, write the method implementations:

不要在类主体中包含方法主体。写两个类,等两个类都完成后,再写方法实现:

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);
}

That way, full information about how the objects of the class will be layed out in memory is available by the time the Connectmethod is implemented. And as a method in the class body and a method declared inlinewill both be inlined the same way, performance will be the same as well.

这样,在Connect实现该方法时,就可以获得有关类的对象如何在内存中布局的完整信息。由于类体中的方法和声明的方法inline都将以相同的方式内联,因此性能也相同。

The only downside is that you won't be able to split these two classes over two headers in a reasonable way.

唯一的缺点是您将无法以合理的方式将这两个类拆分为两个标头。

回答by Luchian Grigore

The only way to do this, if both your classes need a full type in their methods, is to separate the implementation to an implementation file.

如果您的两个类都需要在它们的方法中使用完整类型,那么唯一的方法就是将实现分离到一个实现文件中。

回答by MvG

If you intend to share large parts of the implementation between X and Y, you might want to do that using a template. One example is the following:

如果您打算在 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;

As template methods are only instantiated when used, you avoid the problem outlined above, as by the time they are instantiated, both types are known. If you later on have differences between Xand Y, you might use inheritance instead of typedef.

由于模板方法仅在使用时实例化,因此可以避免上述问题,因为在实例化它们时,两种类型都是已知的。如果您以后在X和之间有差异Y,您可以使用继承而不是typedef

回答by edW

You can place class B into class A

您可以将 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;
}