【问题标题】:Defining unnamed class member functions?定义未命名的类成员函数?
【发布时间】:2015-05-20 15:30:59
【问题描述】:

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

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();

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

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; }

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

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

【问题讨论】:

  • 如果 Sub1 和 Sub2 将成为 Foo 的数据成员,请考虑使用结构。然后,您也可以消除对 Get 函数的需求。
  • 如果您的内部课程超过structs,您可以考虑将它们移出课程并进入私人namespace
  • 如果使用未命名的内部类,编译器如何知道使用哪个GetX 函数?你不能通过类名来引用,因为没有。
  • 为了演示我的问题,对实际代码进行了简化,内部类不仅仅是 Foo 的数据成员。
  • @AmiTavory 私有命名空间听起来很有趣.. 你有更多相关信息吗?

标签: c++ class definition member-functions


【解决方案1】:

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

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

由于不存在类名,因此不可能对成员函数进行类外定义。 GCC 在这种情况下允许使用 decltype-specifiers 的事实是一个错误。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      相关资源
      最近更新 更多