2

我知道定义和常量之间的区别在于常量具有类型,而在宏和函数之间,函数被调用和类型化,而宏是无类型的内联。结构和类之间没有太大区别,但我认为除了公共/私有默认值之外没有区别(我在这里只讨论 C++,而不是 C)。

无论如何,与使用 C++ 版本、常量、函数和类相比,使用定义/宏/结构的代码是否更有效、更有益,或者至少更简洁?

具体来说,因为这只是它们之间没有明显区别(至少在最终程序中)的一个,所以使用结构比使用类更好吗?如果没有效率方面的问题,你有什么使用它们的约定利用?

4

6 回答 6

5

通常,在 C++ 程序中,我可能将 astruct用于简单的数据聚合,例如Point包含 anx和 a的结构y。我会使用具有与之关联的行为class(成员函数)的对象。

这当然只是一个约定,因为除了上面提到的两个细节(默认继承和默认成员可见性)之外,编译器对它们的处理几乎相同。

于 2009-10-14T22:18:41.467 回答
2

宏通常被看不起(可能是完全正确的),因为它们没有任何类型安全性。但是,它们确实对您无法在 C/C++ 中直接执行的操作很有用,特别是用于将类型、变量名和枚举生成字符串以嵌入代码中的字符串化运算符 (#):

#define STRINGIZE(ARG) #ARG

宏对于有大量重复代码的样板代码也很有用,例如将枚举的每个成员插入表中。使用宏比使用函数更简洁。例如,MFC 以这种方式使用宏来定义消息处理程序。

于 2009-10-14T22:55:24.713 回答
0

无参数#defines 与consts:

只要宏实际上被一个不变的常数或一个不变的变量代替,两者都达到了同样的效果。但如果前一种说法不成立,就会有一些细微的差别。让我们以下面的类为例:

class my_class {
    explicit my_class(int i);
    explicit my_class(const my_class& copy_from);
};

// implementation defined elsewhere, it's irrelevant

如果您执行以下操作:

#define MY_CONST_OBJECT my_class(1)
my_class obj1(MY_CONST_OBJECT);
my_class obj2(MY_CONST_OBJECT);

那么my_class参数为 an的构造函数int被调用两次。以下代码是非法的:

my_class& ref1 = MY_CONST_OBJECT;
my_class& ref2 = MY_CONST_OBJECT;

但是,如果您执行以下操作:

const my_class my_const_object(1);
my_class obj1(my_const_object);
my_class obj2(my_const_object);

那么my_class参数为 an的构造函数int只被调用一次。而原本非法的代码现在合法了:

my_class& ref1 = my_const_object;
my_class& ref2 = my_const_object;

参数#defines 与inline函数:

只要宏参数不是表达式,两者都实现相同的功能。但如果前一种说法不成立,就会有一些细微的差别。我们以这个宏为例:

#define MAX(A,B) = ((A) < (B)) ? (A) : (B)

此宏不能将rand()(或任何行为影响整个程序状态和/或依赖于它的函数)作为参数,因为rand()会被调用两次。相反,使用以下函数是安全的:

template < class _Type >
_Type max( _Type a, _Type b ) { return (a < b) ? a : b ; }

structs 与classes

除了前者的基类和成员的默认访问说明符 is和后者的 is之外, structs 和es之间没有真正的区别。但是,声明具有方法和行为的 s 是不文明的,并且声明仅具有可直接访问的原始数据的 es 也是不文明的。classpublicprivatestructclass

声明 aclass意味着用作 a struct,如下所示:

class my_class {
public:
    // only data members
};

味道不好。struct带有构造函数的 s 可能有一些用途,例如不允许使用垃圾数据进行初始化,但我也建议不要使用它们。

于 2009-10-14T23:38:17.307 回答
0

定义\宏和常量\函数之间更重要的区别是范围。

常量应该永远是一个胜利,因为编译器会优化它们以执行和定义,同时保持它们的清晰度。

函数的情况类似于您可以使用宏执行的任何操作,您可以使用函数更安全地执行任何操作,而且我还没有运行过没有提供某种方式强制内联以使行为与宏情况相同的编译器。

于 2009-10-14T22:17:58.177 回答
0

我更喜欢函数和常量而不是定义和宏,因为它们在语义上更明确,因此您可以通过 IDE 和编译器获得更有意义和可控的反馈。

于 2009-10-14T22:26:34.977 回答
0

具体来说,因为这只是它们之间没有明显区别(至少在最终程序中)的一个,使用结构比使用类更好吗?如果没有效率方面的问题,你有什么使用它们的约定利用?

定义内存块时结构更好。例如,Windows API 有一个名为 CreateDialogIndirect 的调用,它的参数之一是这样描述的内存块:

[在]指向包含 CreateDialogIndirect 用于创建对话框的模板的全局内存对象的指针。对话框模板由一个描述对话框的标题和一个或多个描述对话框中每个控件的附加数据块组成。模板可以使用标准格式或扩展格式。在标准模板中,标头是一个 DLGTEMPLATE 结构,后跟附加的可变长度数组。每个控件的数据都包含一个 DLGITEMTEMPLATE 结构,后跟附加的可变长度数组。

这一切听起来很复杂。当然,如果您尝试分配内存的堆分配缓冲区并尝试根据描述填充它。但是,您可以使用结构来简化工作:

 struct {
    DLGTEMPLATE t;
    short noMenu;
    short defaultClass;
    short title;
  } templ;

  templ.t.style = style;
  templ.t.dwExtendedStyle = extendedStyle;
  templ.t.cdit = 0;
  // etc...
  HWND hDlg = ::CreateDialogIndirectParam(hInstance,
                                          &templ.t,
                                          hWndParent,
                                          (DLGPROC)DialogProc,
                                          NULL);

我认为在这种情况下,结构显然是比类更好的选择。它适用于一个类,但这看起来很奇怪,你不同意吗?

于 2009-10-14T22:45:18.587 回答