C++从另一个类调用函数

14

我对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”使用未定义的类B。

我已经尝试将它们更改为指针/ 友元,但是我仍然得到相同的错误。


你能展示完整的代码吗? - Vijay
@AlokSave不起作用,他正在从类A继承... 他需要将接口和实现分别拆分到.h和.cpp文件中。并在A.cpp中#include "B.h" - miguel.martin
看起来是循环依赖。类B继承了A,因此需要A类的功能。然而,类A在使用CallFunction方法时需要类B的功能。这两个类中必须先定义一个。 - RageD
7个回答

17
    void CallFunction ()
    {   // <----- At this point the compiler knows
        //        nothing about the members of B.
        B b;
        b.bFunction();
    }

这是因为C语言中的函数不能互相调用,除非它们中至少有一个被声明为函数原型。

为了解决这个问题,我们需要确保两个类在使用之前都已经被声明。我们将声明和定义分开。这篇MSDN文章详细介绍了关于声明和定义的内容。

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

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

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

4
您需要做的是将 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),因此编译器对此没有问题。但它对它们指向的对象一无所知(简单地说:只知道大小/边界,而不知道内容)。
因此,只要您使用了所有指针大小相同的知识,就可以在任何地方使用它们。但是,如果您想使用它们指向的对象,则此对象的类必须已经被定义并被编译器所知。
最后澄清一下:对象的大小可能不同,与指针不同。指针是一个数字/索引,它指示RAM中存储某些内容的位置(例如索引:0xf6a7b1)。

我认为解释为什么它能够工作比如何使其工作更加重要。 - nishantjr
我已经在底部解释过了。 - therealszaka
谢谢Dupadupa,你的答案也起作用了,但nir打字更少:P非常感谢你的帮助。 - CM99
@CM99 好的 :) 我只是想顺便解释一下为什么你可以在那里放置指针,但不能放置对象 :) - therealszaka

1

在开始时,B类仅被声明而未被定义,这是编译器抱怨的原因。根本原因是在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();
 }

这有点正确但有些误导性。他实际上存在循环依赖。他试图在基类中调用继承类的方法。 - RageD

0

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


0

前向声明 class B 并交换 AB 的定义顺序:先写 B,再写 A。无法调用前向声明的 B 类的方法。


0

你也可以看看奇怪的递归模板模式,并类似于此解决你的问题:

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

0

这是我对问题的解决方案。尽量保持简单明了。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接