多态性 - “{token”错误之前的预期类名

时间:2014-04-05 21:06:05

标签: c++ polymorphism

我知道之前已经发布了很多次,但没有一个解决方案能够提供帮助。我正在尝试从一个超类创建多个子类(在这个例子中,Value-> Fraction-> RationalFraction和Value-> Fraction-> IrrationalFraction),但我一直收到这个错误。我认为它来自循环包含,但我不知道如何在没有它的情况下使分数代码工作。当我构造Fraction时,根据构造函数,它会创建一个Irrational或Rational Fraction,但是我需要在这些子类中包含Fraction,它会创建一个集群。错误发生在RationalFraction和IrrationalFraction中,我似乎无法解决它。有没有更顺畅的方法来实现这个或至少一种方法来修复错误?对不起,如果已经回答了这个问题,我仍然是多态的新手。

Value.h

#ifndef VALUE_H
#define VALUE_H

#include <string>
using namespace std;

class Value
{
public:
    Value();
    virtual ~Value();
    string type;
    virtual string getType() = 0;

protected:
private:
    virtual Value* simplify() = 0;
};

#endif // VALUE_H

Fraction.h

#ifndef FRACTION_H
#define FRACTION_H
#include "Value.h"
#include "RationalFraction.h"
#include "IrrationalFraction.h"
#include <string>

using namespace std;


class Fraction: public Value
    {
    private:
    RationalFraction* rtF;
    virtual Fraction* simplify() = 0;
    IrrationalFraction* irF;
public:
    Fraction(int n, int d);
    Fraction(string n, int d);
    virtual ~Fraction();
    virtual string getType() = 0;
    int numer;
    int denom;
protected:

};

#endif // FRACTION_H

Fraction.cpp

#include "Fraction.h"

#include <iostream>

using namespace std;

Fraction::Fraction(int n, int d) {
    rtF = new RationalFraction(n,d);
}
Fraction::Fraction(string n, int d){
    irF = new IrrationalFraction(n, d);
}

Fraction::~Fraction()
{
    delete rtF;
    delete irF;
}

IrrationalFraction.h

#ifndef IRRATIONALFRACTION_H
#define IRRATIONALFRACTION_H

class IrrationalFraction : public Fraction
{
    public:
        IrrationalFraction(string n, int d);
        virtual ~IrrationalFraction();
    protected:
    private:
        IrrationalFraction* simplify();
};

#endif // IRRATIONALFRACTION_H

RationalFraction.h

#ifndef RATIONALFRACTION_H
#define RATIONALFRACTION_H

using namespace std;


class RationalFraction: public Fraction
{
    public:
        RationalFraction(int n, int d);
        virtual ~RationalFraction();
        int numer;
        int denom;
    protected:
    private:
        RationalFraction* simplify();
};

#endif // RATIONALFRACTION_H

谢谢你们!

这是错误消息: include\RationalFraction.h|8|error: expected class-name before '{' token| include\IrrationalFraction.h|5|error: expected class-name before '{' token| ||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

6 个答案:

答案 0 :(得分:1)

1 首先,您需要使用前向类声明替换 RationalFraction.hIrrationalFraction.h的包含,如下所示:

class RationalFraction;
class IrrationalFraction;

2 其次,您需要在文件Fraction.cpp中添加这些包含。

3 第三,您需要在Fraction.hRationalFraction.h中添加IrrationalFraction.h的内容。

4 第四,您需要在这两个类中添加getType的实现。

5 第五,为避免名称冲突等严重问题,您需要从标题中删除using namespace std;

6 第六,为避免双重删除,即未定义的行为,您必须禁止复制或处理复制。处理复制的一种方法是使用智能指针而不是原始指针。另一个是定义复制构造函数和复制赋值运算符(这有点过于简单,但你可以很容易地找到细节:google为“三个规则”)。

7 Fraction的构造函数无条件地调用IrrationalFraction的构造函数,该构造函数调用Fraction的构造函数。这是无限递归,必须以某种方式解决。当你开始测试时,你会发现它。


这里的设计看起来非常像Java。

您是否考虑过课程模板?

答案 1 :(得分:0)

RationalFraction.h的第8行说

class RationalFraction: public Fraction

但该文件中的任何地方都没有声明Fraction。您

#include "Fraction.h"

如果您打算使用在其中声明的内容。

请注意,Fraction.h包含RationalFraction.h iteslf。如果你不解决这个问题,你将遇到循环标题依赖问题,这基本上意味着noithing将起作用。您可能希望使用RationalFractionIrrationalFraction的前向声明,而不是包含其标题。

答案 2 :(得分:0)

我不认为你的设计非常好,但除此之外,还有一些明显的问题:

1使用尚未声明的名称,例如RationalFraction.h中的Fraction

2你可以使用指向对象的指针(如RationalFraction* rtF;)而没有对象的定义:你需要的只是一个声明。

答案 3 :(得分:0)

你错过了一些&#34; #include&#34; s。

当您实现继承时,编译器期望您将从类继承。并且编译器不知道&#34;分数&#34;是一个类,因为你不包括他的.h文件

答案 4 :(得分:0)

你不能拥有像RationalFraction和Fraction这样的类来嵌入彼此。您应该使用一种名为前向声明What are forward declarations in C++?)的技术。简而言之,这意味着您可以像下面一样声明两个类RationalFraction和IrrationalFraction,而不包括两个头文件。你需要的只是保留两个指向这些类的指针,因此指针大小是固定的并且由编译器知道(4或8个字节,取决于你的PC的处理器架构)。

#ifndef FRACTION_H
#define FRACTION_H
#include "Value.h"
#include <string>

using namespace std;

class RationalFraction;
class IrrationalFractional;
class Fraction: public Value
    {
    private:
    RationalFraction* rtF;
    virtual Fraction* simplify() = 0;
    IrrationalFraction* irF;
public:
    ...
    ...
};

答案 5 :(得分:0)

您必须在RationalFraction.h和IrrationalFraction.h中包含Fraction.h。另外,当你在Fraction.h中包含RationalFraction.h和IrrationalFraction.h时,编译器碰巧找到类声明

class  RationalFraction: public Fraction

在看过Fraction声明之前。您只能将完全声明的类用作基类。您可以通过在Fraction.h中声明RationalFraction和IrrationalFraction来解决这个问题:

#ifndef FRACTION_H
#define FRACTION_H
#include "Value.h"
#include <string>

using namespace std;

class RationalFraction;
class IrrationalFraction;

class Fraction: public Value
    {
    private:
    RationalFraction* rtF;
    virtual Fraction* simplify() = 0;
    IrrationalFraction* irF;
public:
    Fraction(int n, int d);
    Fraction(string n, int d);
    virtual ~Fraction();
    virtual string getType() = 0;
    int numer;
    int denom;
protected:

};

#endif // FRACTION_H

这通知编译器有类RationalFraction和IrrationalFraction。你不能对前向声明的类型做很多事情,因为编译器不知道关于类的任何关系,特别是对象的大小。但是你可以做的是delcare指针和对它们的引用,所以对于Fraction来说这就足够了。

我不确定在基类构造函数中实例化子类时Fraction :: Fraction会发生什么。我的猜测是这是一个无限递归。我想你想要一个像工厂一样的东西,但它不会这样。