【问题标题】:C++ Calling a function from another classC++调用另一个类的函数
【发布时间】:2012-12-19 20:10:15
【问题描述】:

C++ 新手,在调用另一个类的函数时遇到问题。

B 类继承自 A 类,我希望 A 类能够调用在 B 类中创建的函数。

using namespace std;

class B;

class A 
{

public:

    void CallFunction ()
    {
        B b;
        b.bFunction();
    }

};

class B: public A
{
public:
    virtual void bFunction()
        {
            //stuff done here
        }

};

在屏幕上看起来一切正常(没有明显的错误),但是当我尝试编译它时,我得到一个错误 C2079 'b' uses undefined class B.

我尝试让它们成为指针/friends,但我遇到了同样的错误。

【问题讨论】:

  • 你能显示完整的代码吗?
  • @AlokSave 不起作用,他从 A 类继承......他需要将他的接口分别从他的实现中拆分为 .h 和 .cpp 文件。和#include "B.h"A.cpp
  • 看起来像一个循环依赖。 B 类需要 A 类的功能,因为它继承了 A。但是,A 类需要B 类的功能才能正确使用CallFunction 方法。必须首先定义其中一个类。

标签: c++ class function


【解决方案1】:
    void CallFunction ()
    {   // <----- At this point the compiler knows
        //        nothing about the members of B.
        B b;
        b.bFunction();
    }

发生这种情况的原因与 C 中的函数在没有至少一个被声明为函数原型的情况下不能相互调用的原因相同。

要解决这个问题,我们需要确保在使用这两个类之前都已声明它们。我们将声明与定义分开。 This MSDN article 更详细地解释了声明和定义。

class A
{
public:
    void CallFunction ();
};

class B: public A
{
public:
    virtual void bFunction()
    { ... }
};

void A::CallFunction ()
{
    B b;
    b.bFunction();
}

【讨论】:

    【解决方案2】:

    您应该做的是将CallFunction 放入 *.cpp 文件中,其中包含 B.h。

    编辑后的文件如下所示:

    B.h:

    #pragma once //or other specific to compiler...
    using namespace std;
    
    class A 
    {
    public:
        void CallFunction ();
    };
    
    class B: public A
    {
    public:
        virtual void bFunction()
            {
                //stuff done here
            }
    };
    

    B.cpp

    #include "B.h"
    void A::CallFunction(){
    //use B object here...
    }
    

    参考您的解释,您已尝试更改 B b;进入指针 - 如果您不在同一个地方使用它,那没关系。您可以使用未定义类的指针(但已声明),因为所有指针都有固定的字节大小(4),所以编译器没有问题。但它对他们指向的对象一无所知(简单地说:知道大小/边界,而不是内容)。

    因此,只要您使用知识,即所有指针大小相同,您就可以在任何地方使用它们。但是如果你想使用他们所指向的对象,这个对象的类必须已经定义并且编译器知道。

    最后澄清一下:与指针不同,对象的大小可能不同。 Pointer 是一个数字/索引,表示 RAM 中的存储位置(例如索引:0xf6a7b1)。

    【讨论】:

    • 我认为重要的是解释它为什么起作用,而不是如何使它起作用
    • 我已经在底部解释过了。
    • 感谢 Dupadupa,您的回答也有效,但 njr 打字较少:P 非常感谢您的帮助。
    • @CM99 ok :) 我只是想顺便解释一下为什么你可以把指针放在那里,但不能放对象:)
    【解决方案3】:

    class B 一开始只是declared,而不是defined,这是编译器抱怨的。根本原因是在类 A 的调用函数中,您引用了 B 类型的实例 b,它是不完整且未定义的。您可以像这样修改源而不引入新文件(只是为了简单起见,实践中不推荐):

    using namespace std;
    
    class A 
    {
    public:
    
        void CallFunction ();
    };
    
    class B: public A
    {
    public:
        virtual void bFunction()
        {
            //stuff done here
        }
    };
    
    
     // postpone definition of CallFunction here
    
     void A::CallFunction ()
     {
         B b;
         b.bFunction();
     }
    

    【讨论】:

    • 这话有点真实,但有点误导。他实际上有一个循环依赖。他试图在他的基类中调用继承类的方法。
    【解决方案4】:

    在 A 中,您使用了 B 的定义,直到那时才给出,这就是编译器给出错误的原因。

    【讨论】:

      【解决方案5】:

      转发声明class B 并交换AB 定义的顺序:第一个B 和第二个A。您不能调用前向声明的B 类的方法。

      【讨论】:

        【解决方案6】:

        这是我对这个问题的解决方案。尽量保持直截了当。

        #include <iostream>
        using namespace std;
        
        class Game{
        public:
          void init(){
            cout << "Hi" << endl;
          }
        }g;
        
        class b : Game{  //class b uses/imports class Game
        public:
          void h(){
            init(); //Use function from class Game
          }
        }A;
        
        int main()
        {
          A.h();
          return 0;
        }
        

        【讨论】:

          【解决方案7】:

          您也可以查看curiously recurring template pattern 并解决类似这样的问题:

          template<typename B_TYPE>
          struct A
          {
              int callFctn()
              {
                  B_TYPE b;
                  return b.bFctn();
              }
          };
          
          struct B : A<B>
          {
              int bFctn()
              {
                  return 5;
              }
          };
          int main()
          {
              A<B> a;
              return a.callFctn();
          }
          

          【讨论】:

            猜你喜欢
            • 2019-07-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多