另外,我现在有个原则,完全不用参数默认值。所有需要参数默认值的地方都可以用重载解决,而使用参数默认值又会有一些很隐晦的问题(尤其和继承联系起来),干脆不用。
在 07-12-12,王磊<wangle...@gmail.com> 写道:
--
新的理论从少数人的主张到一统天下,并不是因为这个理论说服了别人抛弃旧观点,而是因为一代人的逝去。
My blog: http://googollee.blog.163.com
2.4.1 引用
我受够了!左值/右值、复制引用/复制值 这些问题已经折磨了我很长时间了。我想,如果要用指针就用指针,不用遮遮掩掩说那是一个引用。如果 boost 不需要支持引用的话,我估计 boost 里面跟模板相关的代码可以减少三分之一。我今天决定了,以后除非调用别人的函数要求传引用,否则我绝对不在自己的代码里面用引用。
2.4.2 private 、 public 和 class
任何暴露在头文件中的东西,都理所当然是 public 的。而需要隐藏的实现,如果有办法隐藏,自然可以放到 cpp 文件中。用 C 的那些办法来隐藏实现,比用自欺欺人的 private 好多了。我们知道 class 和 struct 在 C++ 中的唯一区别就是 class 默认成员为 private ,由于 private 是自欺欺人的,所以我们在一切地方都用 struct 代替 class
On Dec 12, 2007 3:41 PM, Atry <pop....@gmail.com> wrote:2.4.1 引用
我受够了!左值/右值、复制引用/复制值 这些问题已经折磨了我很长时间了。我想,如果要用指针就用指针,不用遮遮掩掩说那是一个引用。如果 boost 不需要支持引用的话,我估计 boost 里面跟模板相关的代码可以减少三分之一。我今天决定了,以后除非调用别人的函数要求传引用,否则我绝对不在自己的代码里面用引用。
const&也不用吗?那用什么来接受临时对象呢?
2.4.2 private 、 public 和 class
任何暴露在头文件中的东西,都理所当然是 public 的。而需要隐藏的实现,如果有办法隐藏,自然可以放到 cpp 文件中。用 C 的那些办法来隐藏实现,比用自欺欺人的 private 好多了。我们知道 class 和 struct 在 C++ 中的唯一区别就是 class 默认成员为 private ,由于 private 是自欺欺人的,所以我们在一切地方都用 struct 代替 class
这么做的动机需要更多解释。是为了解二进制依赖吗?如果是像std::complex这样的值类型又如何呢?
在2007-12-12来自pilo...@gmail.com的邮件[[TopLanguage] Re: 我最近的 C++
编码风格]中写到:
> 维护性方面,项目大了代码多了之后的问题,
--
DEBUG是件快乐的事情 <xuzi...@gmail.com>
class Derived : public Base
{
virtual func(int arg = 2);
};
Base *b = new Derived();
b->func(); // 默认参数是多少?
至于由于维护造成重载函数间有的有默认参数,有的没有,结果编译器调用的不是真正预期调用的(比如删掉了一个默认参数,结果编译器不报错,转去调用领一个了)……
在 07-12-12,徐梓鼎<xuzi...@gmail.com> 写道:
在2007-12-12来自goog...@gmail.com的邮件[[TopLanguage] Re: 我最近的 C++
编码风格]中写到:
> 比如:
> class Base
> {
> virtual func(int arg = 1);
> };
>
> class Derived : public Base
> {
> virtual func(int arg = 2);
> };
>
> Base *b = new Derived();
> b->func(); // 默认参数是多少?
--
DEBUG是件快乐的事情 <xuzi...@gmail.com>
--
DEBUG是件快乐的事情 <xuzi...@gmail.com>
void func(someClass *a); // 一般传一个class都是这么传吧?但这个a实际是引用语义。这样someClass就缺乏了值语义
void func(int a); // 这个a是值语义
void func(int *a); // 这才是a的引用语义,只是这种语义是从内存模型层面上区分的
而如果用引用,就可以在语法层面区分
void func(someClass &a); // 明确的引用语义
void func(const someClass &a); // 明确的值语义
void func(int &a); //引用语义
void func(int a); //依旧是值语义
但结果这样做却导致了值语义的不统一,这也是楼主抛弃引用的原因吧?(为了解决一个问题,引入了另一个问题)
估计等0x加入右值引用后,这个问题会好一些。
在 07-12-13,buhongbo<buho...@gmail.com> 写道:
其实,一般内部使用的函数,很少检查指针是否为空,这个动作是在接口函数里保证的。
在 07-12-13,red...@gmail.com<red...@gmail.com> 写道:
本来要解决应用领域的问题已经不容易了, 还要我脑海里面, 随时装一堆规则: 这
个操作符重载必须返回引用, 那个必须返回对象, 这个生活未免太过沉重 ---- 对
于很多人可能不成问题, 但是我的机械记忆力奇差, 不想在这里花费精力.
至于 swap 之类, 我宁愿用
template <T>
void swap(T *a, T *b)
{
}
由于inline, 调用起来不会因为指针而有额外开销, 而我调用 swap 的时候, 用到
&, 我并不会觉得不方便, 反而让我明确地知道, 这两个参数可能会被修改, 以后
阅读代码的时候, 更容易看出来, 变量在哪里被修改 ---- 写代码是一次, 调试是
n次, 阅读代码, 是整个代码生命周期, 比项目可能还长命.
说到调用 swap 的时候, 传一个 NULL 进去 ? 那是谁, 站出来 ? 下次不改, 就炒掉.
总结, 引用解决问题的同时带来其他问题, 指针更简单更一致. 我脑袋里面的 L1,
L2 cache 不够大, 应付业务层面问题的时候, cache 已经满了, 不想再面对这些
问题.
BTW:
其实我对用 macro 实现 SWAP 也不反感,
如果一个人给 SWAP() 提供的参数还带副作用, 那只能证明这个人太迟钝, 没有什
么其他好说的了, 这么简单的规则都记不住.
macro 被 C++ 评为很邪恶, 但其实我觉得macro 最大的问题是没有作用域, 容易
冲突. 参数副作用这个问题, 比起 C++ n 多规则, 实在是一个太简单的规则.
red...@gmail.com 写道:
其实运算符重载的诱惑是最大的,也是最危险的吧。毕竟大家都不是学数学的,对于某个运算符需要满足哪些要求并不了然于心。
而且,很多时候理论上的东西到了实际层面就变了,比如:两个time_t相减,返回的应该是个类似timediff的东西,而不是time_t类型,但如果真的写timediff
& operator-(time_t,
time_t),实际用起来又会遇到很多这样那样的问题(比如STL好像要operator-满足一定要求吧?)
这个目前除了干净的禁止运算符重载,有比较好的解决办法么?
在 07-12-13,red...@gmail.com<red...@gmail.com> 写道:
至于操作符重载的时候, 不用引用不行这个问题, 对我来说, 都不是问题了, 因为
我不用操作符重载.
我宁愿老老实实用函数调用的方式写代码, 虽然不漂亮, 但是可靠, 不容易碰到陷阱.
本来要解决应用领域的问题已经不容易了, 还要我脑海里面, 随时装一堆规则: 这
个操作符重载必须返回引用, 那个必须返回对象, 这个生活未免太过沉重 ---- 对
于很多人可能不成问题, 但是我的机械记忆力奇差, 不想在这里花费精力.
至于 swap 之类, 我宁愿用
template <T>
void swap(T *a, T *b)
{
}
由于inline, 调用起来不会因为指针而有额外开销, 而我调用 swap 的时候, 用到
&, 我并不会觉得不方便, 反而让我明确地知道, 这两个参数可能会被修改, 以后
阅读代码的时候, 更容易看出来, 变量在哪里被修改 ---- 写代码是一次, 调试是
n次, 阅读代码, 是整个代码生命周期, 比项目可能还长命.
说到调用 swap 的时候, 传一个 NULL 进去 ? 那是谁, 站出来 ? 下次不改, 就炒掉.
总结, 引用解决问题的同时带来其他问题, 指针更简单更一致. 我脑袋里面的 L1,
L2 cache 不够大, 应付业务层面问题的时候, cache 已经满了, 不想再面对这些
问题.
BTW:
其实我对用 macro 实现 SWAP 也不反感,
如果一个人给 SWAP() 提供的参数还带副作用, 那只能证明这个人太迟钝, 没有什
么其他好说的了, 这么简单的规则都记不住.
macro 被 C++ 评为很邪恶, 但其实我觉得macro 最大的问题是没有作用域, 容易
冲突. 参数副作用这个问题, 比起 C++ n 多规则, 实在是一个太简单的规则.
说实话C#在这个问题上做得就不错,ref和out关键字的引入非常醒目地标识出了哪些变量会被修改。
说到调用 swap 的时候, 传一个 NULL 进去 ? 那是谁, 站出来 ? 下次不改, 就炒掉.
你自己挖的坑,自己不盖盖子,说掉进去的人活该?
你可以测试一下你的同行,或者新来的 同事,在有编译器帮助的情况下,看看多少人能够一次把SWAP写的完全正确?
macro 被 C++ 评为很邪恶, 但其实我觉得macro 最大的问题是没有作用域, 容易
冲突. 参数副作用这个问题, 比起 C++ n 多规则, 实在是一个太简单的规则.
我认为,如果编译器可以制止的陷阱,那就不算陷阱.编译器无能为力的才算.对于宏,编译器基本残废.
> 2.4.1 引用
> 我受够了!左值/右值、复制引用/复制值 这些问题已经折磨了我很长时间了。我想,如果要用指针就用指针,不用遮遮掩掩说那是一个引用。如果 boost
你比我更激进.
我也很讨厌调用一个函数, 要去查原型才知道我的变量会不会被修改, 所以函数参数中我不用引用.
不过我还会在一些地方用引用, 就是类的成员变量, 用引用, 表明了态度--不能为空 & 只能设置一次.
> 4.2 时间
> 不使用任何 C++ 类,一律传整数,比如 time_t 或者其他自定义的整数 。强大的 Boost.Date_Time 可以拜拜了。
时间啊, 时间啊, c/c++, delphi 里面的时间相关的函数, 都让人头痛无比, 好多个类型, 好多个调用, 让我从来都记不
住, 每次要查找的时候, 都感到很悲愤.
python 里面也不是很简单.
我讨厌时间.
这个观点其实现在越来越流行了,TIC的作者也说过:在太多的地方,我们其实需要的是Iterator,结果我们传递了Container。
引用其实很好,至少对我来说,引用简化了大量的空指针判断。同时,它跟对象语法的一致性也是我喜欢的。
重载的威力真不小。
如果把重载也看作一种多态,那么再加上其他几种多态,将来会不会发展到成为一种完整的元编程机制?
我觉得我们没有必要在乎是不是语法糖,只要不是语法毒药,吃起来甜的都要吃。
只要增加了我们的抽象能力,解放了我们的手指,提高了我们的生产力。