定义未命名的类成员函数?

时间:2015-05-20 15:30:59

标签: c++ class definition member-functions

我目前在我的Foo.h中定义了两个未命名的类:

?is.infinite

此代码编译得很好,它使用如下:

class Foo {
public:
    Foo();

    class {
    private:
        int x;
        int y;
    public:
        int GetX() { return x; }
        int GetY() { return y; }
    } Sub1;

    class {
    private:
        int x;
    public:
        int GetX() { return x; }
    } Sub2;
}

但是,现在我想将成员函数定义移动到源文件。我知道将此类拆分为头文件和源文件的唯一方法是命名类:

foo.h中:

 Foo temp;
 int Ax, Ay, Bx;
 Ax = temp.Sub1.GetX();
 Ay = temp.Sub1.GetY();
 Bx = temp.Sub2.GetX();

Foo.cpp中:

class Foo {

private:    
    class A {
    private:
        int x;
        int y;
    public:
        int GetX();
        int GetY();
    };

    class B {
    private:
        int x;
    public:
        int GetX();
    };

public:
    Foo();
    A Sub1;
    B Sub2;

}

然而,这段代码并不是我想要的,因为它很难看,而且我一开始并不想要一个命名类。

是否可以将类拆分为头文件和源文件?或者这只是糟糕的代码设计?

2 个答案:

答案 0 :(得分:1)

不幸的是,这是不可能的。第9.3节/ 5:

  

如果成员函数的定义在词法之外是词法上的    定义,成员函数名称应由其限定    使用::运算符的类名。

由于不存在类名,因此不可能有成员函数的类外定义。 GCC允许在此上下文中使用decltype-specifiers的事实是一个错误。

答案 1 :(得分:0)

至少使用gcc,您可以使用decltype来解决问题:

int decltype(Foo::Sub1)::GetX() { return x; }

但是,正如Columbo已经指出的那样,它不符合标准。因此,如果以后的gcc版本拒绝对此进行编译,请不要怪我。但是我们所有人现在都认为gcc从来没有对标准合规性持怀疑态度,并且gcc团队有很强的保留语言扩展的趋势,前提是它们都是毫不含糊的(显然,这里就是这种情况)至少对某些程序员有用。一段时间以来,许多这些gcc扩展最终已成为标准的一部分。

尽管如此,clang和其他大多数编译器可能会拒绝此构造并显示错误消息:

'decltype' cannot be used to name a declaration

但是甚至可以欺骗clang来接受decltype窍门。我们只需要做一个typedef

typedef decltype(Foo::Sub1) Sub1type;
int Sub1type::GetX() { return x; }

当然,这与命名未命名的类没有太大不同。 typedef解决方案的优势可能仍然是,您可以隐藏私有名称空间中的类型名称。