“{”标记之前的预期类名

时间:2014-03-31 20:15:19

标签: c++

到目前为止,我已经查找了大多数针对此错误案例的典型解决方案,但其中没有这些解决方案似乎适用于我的代码。我正在使用dev-c ++

有问题的课程的结构如下。 m.hh

#ifndef M_H
#define M_H

#include "z.hh"
#include <iostream>
#include <string>


using namespace std;

class M: public Z
{                        /* this line is marked by the compiler as errorneous */
void m1();
void m2();
};

#endif

m.cpp

#include <iostream>
#include <string>
#include "m.hh"

using namespace std;

void M::m1()                    {/*bla bla*/};
void M::m2()                        {/*bla bla*/};
}

编辑: z.hh

#ifndef Z_H
#define Z_H

#include "m.hh"
#include <iostream>
#include <string>


using namespace std;

class Z;

static Z* s(string g, string i);

#endif

z.cpp

#include "z.hh"
#include <iostream>
#include <string>


class Z
{


public:
    string i;
    string g;

    void set_i(string im)                       {i = im;}
    string get_i()                              {return i;}
    string get_g()                          {return g;}
    virtual void m1()=0;
    virtual void m2()=0;
    Z* s(string g, string i)    {
        Z * z;
        if(g=="m"){
            M * z = new M;

        }
    }

};

谢谢!

3 个答案:

答案 0 :(得分:3)

#include "m.hh"移除z.hh以修复循环包含。

答案 1 :(得分:2)

问题

您无法从不完整的类型派生,Z位于m.hh

从类型派生时,编译器必须知道所述类型的定义。想象一下,你试图从类型Z的对象上调用M的派生成员函数,编译器如何知道这样的调用是否是一个有效的构造,而不知道Z是否实际声明这样的成员?

更相关的一点是,M如何在不知道Z是什么的情况下初始化Z


解决方案

class Z的定义移至z.hh,并将其成员函数的定义保留在z.cpp中(与M分开m.hh的方式相同}和m.cpp)。

答案 2 :(得分:1)

嗯,z.cpp文件实际上是一个类声明,应该是一个头文件。当你处理指向该类的指针时,前向decalaration就足够了,但不能继承一个指针(编译器确实需要知道z的类布局)。

实际上并不需要z.hh,并且其中的函数声明不是您的想法(它不是成员函数声明)。您可以删除它并将z.cpp重命名为z.hh。

好的,与@Luchian Grigore的交流让我意识到你可能想要的东西以及为什么你有两个z.hh&#34;。 Z是产生M,但M继承自Z,因此存在循环依赖。在C / C ++中,打破这样一个循环的方法是限制其中一个类需要知道的另一个:为了声明一个成员函数s,它产生一个指向新M Z的类声明只需要一个类型名M,而不是整个类声明。所以只需要在Z的声明中引入类型名称M的前向声明(class M;)就足够了;如果指向M对象的指针作为指向基础的指针返回,则当Z 声明时,甚至根本不需要Z,M的名称。

工厂函数的定义(无论是文件静态还是成员函数)需要,如果要生成M,M的完整声明。这将是一个seaparate cpp文件,其中包含一个包含M&#39完整声明的完整标题。