在C ++中,有没有办法以类似于嵌套typedef的方式定义类中的嵌套宏/常量,或者实现类似功能的方法?动机通常是模板使用的宏。
class SomeClass
{
public:
#define SomeConstant 123
};
int x=SomeClass::SomeConstant;
当然,静态const成员可以完成这项工作,但那些是物理变量,而我正在寻找一种简单的宏观行为。
答案 0 :(得分:8)
你无法用宏做你想做的事。宏没有确定范围的概念。
但对于简单的int值,您可以使用枚举执行所需的操作。
class SomeClass
{
public:
enum {
SomeConstant=123
};
};
int x=SomeClass::SomeConstant;
值的完全范围名称,但没有空间,即使在调试版本中 - 如果您愿意,也无法获取其地址。
答案 1 :(得分:6)
就地声明和定义的Const值正是您所需要的:编译器可以并且将完全优化它们,因此它们最终与首先使用#define完全相同,但具有以下优点:严格范围。
class SomeClass {
public:
static const int someValue = 10;
};
这不占用任何额外空间 - 没有分配内存来存储“someValue”。您可以证明这一点:如果您尝试使用“someValue”作为真实对象(即您尝试获取其地址),那么链接器会告诉您它未定义。
答案 2 :(得分:2)
宏完全忽略范围 - 它们在C ++编译之前被扩展。你不能这样做。
使用静态const通常会导致不分配变量 - 编译器将其视为常量。
答案 3 :(得分:1)
宏预处理器通常不了解语言上下文;因此,他们不知道“阶级”是什么让“在课堂上筑巢”一开始就没有意义。
对于你想要的,要么使用静态const,要么使用全名(假设预处理器允许使用宏名称中的冒号,而不是100%确定) - 虽然它不允许你继承派生类的常量:
#define SomeClass::SomeConstant 123
答案 4 :(得分:1)
您可以使用模板执行此操作:
template < int someConstant = 123 > class SomeClass { public: void outputConstant() { cout << "We think the answer is:" << someConstant; } }
但这并不是你想要的,因为你必须将类的实例声明为:
int main(int argc, char *argv) { SomeClass<123> myInstance; }
我知道其他人已经解释了有关宏的问题,但允许我补充一点:#define
由预处理器而不是编译器处理。在标准中有一个称为“翻译阶段”的部分,它更详细地解释了这一点,但是对于你的问题,重点是在编译类之前评估宏,并且不知道#define发生的范围。 / p>
关于这个主题的权威书籍(在编译阶段用模板编程)是Modern C++ Design: Generic Programming and Design Patterns Applied, by Andrei Alexandrescu。
答案 5 :(得分:0)
我不明白你对使用静态const的反对意见。 它不会影响类的大小,编译器将进行优化以实现您从宏中获得的内容。
答案 6 :(得分:0)
“静态成员是物理变量”。
有什么反对的?反对这一点的唯一原因是内存使用。但由于成员是静态的,因此内存只会被预期的内容占用一次。
相反,使用宏,竞争将在二进制文件中的每个使用位置出现。
编辑: 如果变量是整数类型,小于指针,则最好在类声明中定义常量。然后优化编译器可以内联调用代码中的值,就像宏一样。