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