标量类型和运算符重载的成员函数

时间:2011-12-03 00:29:38

标签: c++

我一直在考虑C ++可能具备的一些功能,有谁知道为什么不支持它们?

  1. 内置类型的成员函数。这可能似乎没有必要,但仍然是一个有趣的功能。示例伪代码:int int::getFirstBit(void) {return *this & 1;} ... int a = 2; a.getFirstBit();这似乎没用,但它也不难实现。随之而来的是以下想法:
  2. 类定义之外的成员函数。我不明白为什么不应该支持这个,除了与访问限制(公共,受保护,私有等)和封装的冲突,但也许只有structs可以拥有此功能。
  3. 非对象类型的运算符重载,可以用于指针或数组。
  4. 我知道这些功能并不是必需的,但它们看起来仍然很酷。是因为它们似乎没有必要,还是因为它们会引起很多麻烦?

2 个答案:

答案 0 :(得分:1)

  

我知道这些功能并不是必需的,但它们看起来仍然很酷。是因为它们似乎没有必要,还是因为它们会引起很多麻烦?

另一部分的一部分。添加到语言中的每个新功能都会增加语言,编译器和程序的复杂性。一般来说,除非有真正的激励需求(或者新功能有助于编写更简单更安全的程序),否则不会添加功能。

截至您建议的特定功能:

1-内置类型的成员函数

没有必要,您可以使用具有免费功能的成员函数以相同的代价执行任何操作,并且用户代码的唯一区别是函数的参数在.之前或在括号内。

使用自由函数无法做到的唯一事情是动态调度(多态),但由于无法从这些类型派生,因此也不能具有多态性。然后,为了能够做到这一点,你需要2。

2-类定义之外的成员函数。

我理解你的意思是扩展方法,就像在C#中一样,新方法可以在外部添加到类型中。如果没有它,这个功能的使用很少,不够简单。然后有复杂性。

目前,编译器可以看到类的单个定义,并且能够确定可以应用于该类型元素的所有成员方法。这包括virtual函数,这意味着编译器可以立即确定虚函数表(而vtable不是标准,所有实现都使用它们)。如果您可以在类定义之外添加虚拟方法,则不同的翻译单元将看到该类型的不同不兼容视图。调度到第三个虚函数可能是在一个.cpp文件中调用foo,而在另一个.cpp文件中调用bar。解决这个问题,而不是将连接阶段的大部分内容推迟到将二进制文件加载到内存中以便执行,这几乎是不可能的,推迟它将意味着语言模型的重大变化。

如果将该功能限制为非虚函数,事情会变得更简单,因为调用将直接调度到函数,但是,即使这样也意味着其他级别的复杂性。使用C ++中的单独编译模型,您最终必须为原始类和扩展方法编写标题,并且在您要使用它的翻译单元中包括两者,在大多数情况下,您可以简化在原始头文件中声明与真实成员方法相同的方法(或自由函数,自由函数确实构成用户定义类型的接口的一部分!)

此外,允许这样做意味着代码中的简单拼写错误可能会产生意外结果。目前,编译器验证成员函数的定义是否具有适当的声明,如果允许检查必须被删除,并且在声明或定义中写入名称时的简单拼写错误将导致两个单独的函数而不是快速修复编译错误。

3-非对象类型的运算符重载

该语言允许为所有用户定义类型(包括类和枚举)重载运算符。对于其余类型,有一组运算符已经定义为具有无法更改的精确语义。再次使用单独的编译模型,这意味着1+2在不同的翻译单元中可能意味着不同的东西,特别是包含的确切组合可能会改变程序的语义,并且会导致破坏 - 你删除了一个依赖在您的标头中,并删除包含const char* + int重载的包含,这反过来意味着包含您的标头的代码中"Hi" + 2的语义从用户定义的操作更改为产生指针到字符串的nul终止符。这真的很危险,因为这意味着程序某个部分的简单更改会导致程序的其他部分不正确。

即使对于没有当前含义的组合(char* + int*),您也可以使用常规函数来提供相同的操作。请记住,在建模的域中,您应该只重载操作符,该操作自然被理解为具有该特定语义,这就是可以重载用户定义类型的原因,但指针不是您网域的一部分,而是语言的一部分,而且在语言中没有"Hi" + new int(5)含义的自然定义。运算符重载的目的是使代码更具可读性,并且在任何没有自然定义的上下文中,运算符重载具有完全相反的效果。

答案 1 :(得分:0)

  1. 因为你可以写一个做同样事情的自由函数。 “成员函数”是否会更加可取,以抵消在标准中批准这一成本并让编译器供应商实现它的巨大成本?否。
  2. 外面到底在哪里?
  3. 见1.