使用SubClass在MainClass中调用函数

时间:2018-04-13 13:36:05

标签: c++ constructor reference

我已经看到了很多答案,如何创建(例如)A类,其中包含对象B bB类,其中包含对象A a

像:

B:

class A;
class B{
  A& a;
};

A:

class A{
  B b;
};

但如果我想在A B中调用Invalid use of incomplete type 'class A'中的函数,我得到:#include "mainclass.h" int main() { MainClass mainClass; mainClass.print(); return 0; } 我能做什么?我想我知道编译器为什么这么说,但我不知道如何修复它。

这是我最新的代码:

Main.cpp的:

#ifndef MAINCLASS_H
#define MAINCLASS_H

#include <iostream>

#include "subclass.h"

class MainClass
{
    SubClass sub;
    public:
        void print() { sub.print(); }
        void printTest() { std::cout << "test" << std::endl; }
};

#endif

MainClass.h:

#ifndef SUBCLASS_H
#define SUBCLASS_H

class MainClass;
class SubClass
{
    MainClass* main;

    public:
        void print() { main->printTest(); }
    protected:

    private:
};

#endif

SubClass.h:

# --table-start--
dataClass=com.icecube.iceman.model.dto.AddressEntity
tableName=address
# --table-fields-start--
fieldName=id
columnName=_id
generatedId=true
fieldName=name
columnName=name
fieldName=zip
columnName=zip
fieldName=country
columnName=country
fieldName=city
columnName=city
fieldName=district
columnName=district
fieldName=street
columnName=street
fieldName=streetnumber
columnName=streetNumber
fieldName=block
columnName=block
fieldName=building
columnName=building
fieldName=type
columnName=type
# --table-fields-end--
# --table-end--

4 个答案:

答案 0 :(得分:2)

您的代码的主要问题是MainClass和SubClass的定义是相互依赖,因此使用标头保护将禁止在同一转换中包含两个头文件单位(即cpp文件和所有包含的头文件的并集。)

子类中的类MainClass的前向声明可以解决这个问题,因为SubClass :: main是一个指针(检查PIMPL惯用语),但是因为你已经在头文件中包含了类方法的实现文件,当SubClass :: print()方法引用MainClass :: printTest()时编译器失败,因为它对类MainClass一无所知,除了它在其他地方定义的事实。

另一方面,如上所述,由于标题保护,在子类h中明确包含mainclass.h来更改前向声明不是解决方案。

简单的解决方案是在.h和.cpp文件中拆分声明和类的实现。如果这样做,编译器将处理多个转换单元:一个用于mainclass.cpp,一个用于subclass.cpp,一个用于main.cpp。在处理subclass.cpp转换单元时,编译器将能够包含mainclass.h文件,并将MainClass的完整定义设置为&#34;参见&#34;一个MainClass :: printTest()方法存在。

这是mainclass.h:

#ifndef MAINCLASS_H
#define MAINCLASS_H

#include <iostream>
#include "subclass.h"

class MainClass
{
SubClass sub;
public:
    void print();
    void printTest();
};

#endif

mainclass.cpp文件:

#include <iostream>
#include "mainclass.h"

void MainClass::print()
{
    sub.print();
}

void MainClass::printTest()
{
    std::cout << "test" << std::endl;
}

subclass.h文件:

#ifndef SUBCLASS_H
#define SUBCLASS_H

class MainClass;
class SubClass
{
    MainClass* main;

public:        
    void print();
};

#endif

subclass.cpp:

#include "mainclass.h"
//#include "subclass.h" // already included with the previous line

void SubClass::print()
{
    main->printTest();
}

最后是main.cpp:

#include "mainclass.h"

int main()
{
    MainClass mainClass;
    mainClass.print();
    return 0;
}

这将编译并将显然工作,因为它将打印字符串&#34; test&#34;即使主指针未初始化,也指向未定义的内存区域

这是因为printTest方法只会产生副作用,即在屏幕上打印。实际上,它不会通过this指针访问MainClass的任何数据成员,因此您没有内存访问冲突。实际上,在未实例化的指针上调用方法是一种未定义的行为,因此最好避免它,以及循环依赖。

答案 1 :(得分:1)

避免在H文件中创建函数体,并将函数体放入Cpp文件中。

MainClass.h:

#ifndef MAINCLASS_H
#define MAINCLASS_H

#include <iostream>

#include "subclass.h"

class MainClass {
    SubClass sub;
    public:
        void print();
        void printTest();
};
#endif

MainClass.cpp:

#include <iostream>

#include "mainclass.h"

void MainClass :: print () { sub.print(); }

void MainClass :: printTest() {std::cout << "test" << std::endl; }

SubClass.h

#ifndef SUBCLASS_H
#define SUBCLASS_H

#include "mainclass.h"

class SubClass
{
    MainClass* main;

    public:
        void print();
    protected:

    private:
};

#endif

SubClass.cpp

#include "mainclass.h"
#include "subclass.h"

void SubClass::print ()
{
    main->printTest();
}

你实际上可以在你的subclass.h中#include“mainclass.h”,因为它是由#ifdef

守护的

答案 2 :(得分:1)

您无法调用尚不存在的函数(MainClass::printTest)。

您可以在SubClass内声明该功能,但在您拥有MainClass定义后对其进行定义。

#include <iostream>

class MainClass;
class SubClass
{
    MainClass* main;

    public:
        void print();
    protected:

    private:
};

class MainClass
{
    SubClass sub;
    public:
        void print() { sub.print(); }
        void printTest() { std::cout << "test" << std::endl; }
};

void SubClass::print() { main->printTest(); }

int main()
{
    MainClass mainClass;
    mainClass.print();
    return 0;
}

答案 3 :(得分:0)

您遇到了设计问题: -

  1. SubClass.h编译器如何知道类MainClass有一个方法printTest,因此它可以链接到它,因为你没有包含{{1}定义的头文件}

  2. 另一个问题是,您甚至无法在MainClass中加入MainClass.h,因为您在其中引用了SubClass.h

  3. SubClass sub;指针MainClass* main;从未初始化,因此此语句main在这里也是错误的。