我目前在我的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;
}
然而,这段代码并不是我想要的,因为它很难看,而且我一开始并不想要一个命名类。
是否可以将类拆分为头文件和源文件?或者这只是糟糕的代码设计?
答案 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
解决方案的优势可能仍然是,您可以隐藏私有名称空间中的类型名称。