在命名空间中定义类的方式

4

我在头文件中按照以下方式在命名空间中定义了一个类:

#ifndef _c1_
#define _c1_

namespace classspace
{
    class Aclass;
}

class Aclass
{
    //body
};

#endif _c1_

我在main.cpp中添加了这个头文件,并在main()函数中创建了一个对象,但是它返回错误:未定义的类'classspace :: Aclass'。这是我的main函数:

void main()
{
    classspace::Aclass b;
}

当我定义类时,使用了以下代码:

class classspace::Aclass
{
    //body
};

错误已解决。 我在Qt主窗口文件中看到了使用第一种方法的代码:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

没有任何错误,正在运行。 在第一种方法中,我的错误是什么?


你能展示一下Qt源代码吗? - Joseph Mansfield
请查看问题,我已经添加了它。 - QT-ITK-VTK-Help
你没有在头文件中“定义”Aclass,而是进行了前向声明。 - John Dibling
6个回答

10

类定义必须与您声明类的命名空间相同。

至于Qt示例,声明在命名空间之外的MainWindow 不是同一个类

它使用Pimpl习惯用法。在命名空间中声明的MainWindow类被用作在命名空间之外声明的MainWindow类中的成员,并且带有其命名空间的限定符:

Ui::MainWindow* ui;

这个类的定义被放在了别处(不同的.cpp文件中),它应该在Ui命名空间中,或者使用命名空间前缀来定义。

谢谢!即使我检查了Qt文件的cpp,它没有命名空间,但是它有一些自动生成的支持文件,这些文件将类定义为命名空间,这实际上解决了我的疑惑。 - QT-ITK-VTK-Help

6
namespace classspace
{
    class Aclass;
}

这个声明在命名空间中定义了一个类。

class Aclass
{
    //body
};

这将在全局命名空间中声明和定义一个具有相同名称的不同类。
class classspace::Aclass
{
    //body
};

这定义了你在命名空间中先前声明的类。

void main()
{
    classspace::Aclass b;
}

这试图实例化在命名空间中声明的类。如果该类尚未定义(仅已声明),则它是不完整的并且无法实例化。

Qt示例涉及两个类:Ui :: MainWindowMainWindow在全局命名空间中。其中一个在Ui中仅被声明,因此在标题中是不完整的。您可以对其进行各种操作,例如声明指向它的指针,但不能实例化它。

大概会有一个单独的源文件来定义Ui类,实例化一个并将指针设置为指向它。

顺便说一下,您不应使用保留名称作为您的包含保护或其他任何内容。另外,main函数的返回类型必须是int


有什么特别的原因导致你给了负评吗?我想纠正任何我做错的地方。 - Mike Seymour

0
namespace classspace
{
    class Aclass;
}

class Aclass
{
    //body
};

这两个类是两个不同的类(但名称相同)。

您正在使用尚未定义的classspace :: Aclass。在命名空间中添加主体:

namespace classspace
{

class Aclass
{
    //body
};

}

0

你在命名空间内声明类,但在命名空间外定义它。因此,声明应该是:

classspace::Aclass

但是定义为实现提供了定义:

::Aclass

命名空间在声明和定义时应该匹配。


是的 - 他回答了你的问题,你的类定义在命名空间之外,它不是同一个类。 - paulm

0

命名空间本质上就是包。在您的Qt示例中,类被前向声明。使用命名空间的一种方法如下:

namespace MyNamespace
{
  class MyClass
  {
  };
}

如果你想像第一个例子那样做,那么你必须进行前向声明。例如:
namespace MyNamespace
{
   class MyClass;
}

class MyClass
{
    //body
};

0

想象一下

namespace foo
{
  class AClass;
}
namespace goo
{
  class AClass;
}

class AClass
{
}

int main()
{
  AClass myClass;
}

我们使用哪个?foo还是goo

你必须指定,要么通过使用名称空间名调用所有使用AClass的地方,即foo::AClass,要么将所有用法放在内部。

namespace foo
{

}

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