定义未命名 class 成员函数?

Defining unnamed class member functions?

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

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 temp;
 int Ax, Ay, Bx;
 Ax = temp.Sub1.GetX();
 Ay = temp.Sub1.GetY();
 Bx = temp.Sub2.GetX();

但是,现在我想将成员函数定义移动到源 file.The 我知道将此 class 拆分为头文件和源文件的唯一方法是将 classes:

Foo.h:

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;

}

Foo.cpp:

int Foo::A::GetX() { return x; }
int Foo::A::GetY() { return y; }
int Foo::B::GetX() { return x; }

但是,这段代码不是我想要的,因为它很丑陋,而且我一开始就不想命名 class。

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

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

If the definition of a member function is lexically outside its class definition, the member function name shall be qualified by its class name using the :: operator.

由于不存在 class 名称,因此成员函数的 class 之外的定义是不可能的。 GCC 在此上下文中允许 decltype 说明符这一事实是一个错误。

至少 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 解决方案的优点可能仍然是,您可以将类型名称隐藏在私有命名空间中。