错误:在'ClassName'之前缺少类型说明符

67
shared_ptr<Shape> circle(new Circle(Vec2f(0, 0), 0.1, Vec3f(1, 0, 0)));

shared_ptr<Shape> rect(new Rect2f(Vec2f(0, 0), 5.0f, 5.0f, 0,
                                  Vec3f(1.0f, 1.0f, 0))              );

我试图理解上述代码为什么不能编译。不知何故,当我尝试创建Rect2f的实例(该类确实从Shape类继承,就像Circle一样在shared_ptr模板参数中指定),我收到以下错误

error: expected type-specifier before 'Rect2f'
error: expected ')' before 'Rect2f'

Circleshared_ptr没有任何问题,一切都很好。只有Rect2f存在问题。

此外,传入构造函数的值是有效的。

那么,这个问题可能是什么呢?我已经在代码中包含了Rect.h。为了简洁起见(以及防止我错过可能影响此问题的文件),我将发布以下内容:

Rect.h

#pragma once

#include <QGLWidget>
#include <GL/glext.h>
#include <cmath>
#include <QDebug>
#include "Shape.h"
#include "Vec3f.h"
#include "rand.h"

const int DEFAULT_SQUARE_WIDTH = 5;
const int DEFAULT_SQUARE_HEIGHT = 5;

typedef enum {
    RC_TOPLEFT,
    RC_TOPRIGHT,
    RC_BOTTOMRIGHT,
    RC_BOTTOMLEFT
} RectangleCorner;

class Rect2f : public Shape
{
public:

    Rect2f(
        Vec2f center = Vec2f(),
        float width = 4,
        float height = 4,
        float radius = 0,
        Vec3f color = Vec3f()
    );

    ~Rect2f();

    inline const float GetWidth( void ) const {
        return mWidth;
    }

    inline const float GetHeight( void ) const {
        return mHeight;
    }

    inline const Vec2f* GetCorner( RectangleCorner rc ) const {
        switch( rc ) {
        case RC_TOPLEFT:
            return mTopLeftCrnr;
            break;

        case RC_TOPRIGHT:
            return mTopRightCrnr;
            break;

        case RC_BOTTOMLEFT:
            return mBottomLeftCrnr;
            break;

        case RC_BOTTOMRIGHT:
            return mBottomRightCrnr;
            break;
        }
    }

    void UpdateCorners();

    virtual void Collide( Shape &s );

    virtual void Collide( Rect2f &r );

    virtual void Collide ( Circle &c );

    virtual bool Intersects( const Shape& s ) const;

    virtual bool Intersects( const Rect2f& s ) const;

    virtual bool IsAlive( void ) const;

    virtual float Mass( void ) const;

protected:

   virtual void Draw( void ) const;
   float mWidth, mHeight;
   Vec3f mColor;

private:
   Vec2f* mTopLeftCrnr;
   Vec2f* mTopRightCrnr;
   Vec2f* mBottomLeftCrnr;
   Vec2f* mBottomRightCrnr;

};

错误函数和文件头的来源(mainwindow.cpp)

#include "ui_mainwindow.h"
#include "Vec2f.h"
#include "Rect2f.h"
#include "SharedPtr.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi( this );

    BoxOfShapes* display = new  InteractiveBoxOfShapes( this, 600, 600 );
    ui->mGridLayout->addWidget( display );
    ui->mStatusBar->showMessage( "status ok" );

    QObject::connect( display, SIGNAL( numShapesChanged( int ) ), this, SLOT( setNumShapes(int) ) );
    QObject::connect( ui->mResetButton, SIGNAL( pressed() ), display, SLOT( resetWorld() ) );
    shared_ptr<Shape> circle(
                new Circle(
                    Vec2f( 0, 0 ),
                    0.1,
                    Vec3f( 1, 0, 0 ) ) );
    /*std::shared_ptr<Shape> rect( <---error
                     new Rect2f(
                        Vec2f( 0, 0 ),
                        5.0f,
                        5.0f,
                        0,
                        Vec3f( 1.0f, 1.0f, 0 )
                    )
                );*/
    shared_ptr< Shape > rect( new Rect2f() ); //error - second attempt 
    display->addShape( circle );
    display->addShape( rect );
}

主函数测试(main.cpp)

#include <QtGui/QApplication>
#include "mainwindow.h"
#include "Rect2f.h"

int main(int argc, char *argv[])
{
    Rect2f rec;

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

问题

从提供的错误信息判断,我错过了什么?还有,如何纠正这个问题?


你是否包含了 Rect2f 的头文件?还是进行了前向声明? - J.N.
1
是的,我已经包含了 Rect2f 的头文件。 - zeboidlund
2个回答

235

对于未来遇到类似问题的人,情况是编译器无法找到你正在使用的类型(即使你的Intelisense能够找到它)。

这可能是由以下原因引起:

  • 你忘记了包含定义它的头文件 #include
  • 你的包含保护(#ifndef BLAH_H)有缺陷(由于错字或复制粘贴错误,你的 #ifndef BLAH_H#define BALH_H 不匹配)。
  • 你意外地两次使用了包含保护(两个单独的文件都使用 #define MYHEADER_H,即使它们位于不同的目录中)。
  • 你忘记了你正在使用一个模板(例如,new Vector() 应该是 new Vector<int>())。
  • 编译器认为你指的是一个作用域,而实际上你指的是另一个作用域 (例如,如果你有 NamespaceA::NamespaceB 和一个 <global scope>::NamespaceB,如果你已经在 NamespaceA 中,它会查找 NamespaceA::NamespaceB,而不会检查 <global scope>::NamespaceB),除非你明确地访问它。
  • 你有一个名称冲突(两个具有相同名称的实体,例如类和枚举成员)。

要显式访问全局命名空间中的某个内容,请使用前缀 ::,就好像全局命名空间是一个没有名称的命名空间一样(例如,::MyType::MyNamespace::MyType)。


1
两个分别在不同子目录中的exceptions.h文件;都有#ifndef __ProjectName__exceptions_语句;其中一个包含另一个。哎呀! - OJFord
这就是为什么我在Visual Studio中安装了clang,这样当我遇到困难时,我可以获得更好的错误信息。 - Dan
2
我在两个文件中使用了相同的保护程序,谢谢,这很有帮助。 - Yogesh Kumar Gupta
如果两个库包含相同的类,则可能会发生非常相似的情况。最近,在开发“Argument”类时,我意外地遇到了这个错误,结果发现有两个“using namespace”(其中一个具有相同名称的未记录类)导致了错误。 - Oliver

9

首先,让我们试着让您的代码更简单一些:

// No need to create a circle unless it is clearly necessary to
// demonstrate the problem

// Your Rect2f defines a default constructor, so let's use it for simplicity.
shared_ptr<Shape> rect(new Rect2f());

好的,现在我们可以看到括号已经明显是平衡的了。那么还有什么问题呢?让我们检查一下以下代码片段的错误

int main() {
    delete new T();
}

这可能看起来像是奇怪的用法,而且确实是,但我非常讨厌内存泄漏。然而,输出似乎很有用:

In function 'int main()':
Line 2: error: expected type-specifier before 'T'

啊哈!现在我们只剩下括号错误了。我无法找到导致这个问题的原因; 然而,我认为您忘记包含定义Rect2f的文件了。

好的,那么 Shape 没有被找到? - zeboidlund
不,Rect2f 没有找到。你需要 #include "Rect.h" - Cactus Golov
请注意,我刚刚在main()函数中发布的作用域错误不应该发生。为了清晰起见,我将在我的问题中发布该函数。 - zeboidlund
@Holland:请展示出导致错误的代码。(这个问题可能过于局部化,适合在IRC上提问,比如在##c++-basic(去掉Qt参考)或Freenode上的#qt频道)。 - Cactus Golov
@Default:我已经删除了链接。我怀疑这个粘贴只是这个答案中的第二个代码片段。 - Cactus Golov
显示剩余4条评论

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