×

Loading...
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务
Ad by
  • 推荐 OXIO 加拿大高速网络,最低月费仅$40. 使用推荐码 RCR37MB 可获得一个月的免费服务

咱接着扯这些个理论:

本文发表在 rolia.net 枫下论坛》class定义了object的layout, object包含着method的实现,为了使用method必须先创建一个object,这就是所谓的OO。
class定义的是object的type。“object包含着method的实现,为了使用method必须先创建一个object”,这个陈述不算严谨,但是也可以接受。不过,这不是OO,只是OO的一个特性。OO的关键是数据和method的结合和封装。
》OO 说一切都是object, 然后又说object 包含data及操作这些data的methods.对于同样一组数据和方法,不同的人会写出不同数量的类,OO 的随意性可见是多么的大。

》如果我想绕开object的创建,直接从class就能得到method,这好像就成了C++里面的static function.
如果要绕开object,直接用C里的函数就好了,没必要在创建另一个ugly的非OO的方式。既然要绕开OO,又何必用什么OO里的class呢?加到class里面,无非给人一种封装的错觉,然后,每一本C++入门书都要花至少一章纠正这种错觉。
》C++支持的东西太多,让人有点儿迷惑。假如我把一个函数同时放在三种地方:一个以静态函数的形式放在多个class里面,一个全局函数,一个放在多个namespace里面,尽管函数体是一模一样的,我能否说它们是一样的呢?我不大清楚C++ compiler是怎样区别这些函数的,是简单实用name mangling, 或是自动添加不同的type涅,或者说想怎么实现就怎么实现,没啥标准。

》再绕回来看OO,一个class包含data (member variable)和method(s),那好,我定义一个class,其member variables是函数指针,那么这个时候,数据和方法并没有本质区别,OO 似乎也就毫无优势可言,对不对?
不好意思,没看明白。
》我想说的是数据和方法没有区别。

》functional programming 说一切都是函数,我觉得更有道理一些。要不咱这样,function也是一种object,可以动态创建。比方说,在C++里面,咱也可以new某个function,如何?
把function做为object,还是OO,不是functional programming。functional programming是把function作为first class citizen,比如Lisp。在C里面,如果用functional programming的paradigm的话,可以用函数指针。
》我想要的是在程序运行时,动态生成函数的多个copy,也就是说在程序运行当中一个函数的代码段可以被任意复制。


我觉得咱这是纯理论忽悠,跟实际应用相去甚远。更多精彩文章及讨论,请光临枫下论坛 rolia.net
Report

Replies, comments and Discussions:

  • 工作学习 / 科技领域杂谈 / 简单技术问题。C++里面类的静态成员函数,有什么常见应用吗?好像可以用来作为线程函数和回调函数,可是,它又不能访问类的非静态成员,为什么非要把它放到类里?我能想到的应用是操作静态数据成员。可是非静态函数也可以操作静态数据成员啊。
    • 可以不通过Object直接调用那个函数。
      例如你有一个类,名为example,里面有一个静态函数:
      static int output_Value (void);
      那么你在调用时不需要声明Object就可以直接调用,像这样:
      // Your code..
      std::cout << example::increase_Value () <<std::endl;
      // Your code after function call..

      类的静态函数和类的静态变量都一样。都不属于特定的某个Object。因此呢,一个类的静态函数只能对同一个类里的静态函数进行操作。原因很简单。静态函数不属于任何一个Object。而非静态函数则属于某个特定的Object。假设你声明了10个example,那么静态函数该怎么知道你想让他修改的非静态函数属于这10个里面的哪一个?
      当然,也正因为这样,this指针在静态函数里也不起作用,理由同上。
      如果英文可以,来这个网站看看=)
      • 补充一个例子(虽然不是个好例子)
        例如你有个游戏,有不同的种类的单位。然后你想让特定种类的单位全部都拥有特殊的加成。例如说:攻击加成。
        那么,第一个想到的是:Loop所有的该类型的单位,加上那个Buffer……
        ok,可以啊……不过……如果要是你有1000个该类型的单位呢?orz..电脑直接跪了……
        好吧,第二个Idea!:用类的静态函数+静态变量。
        一个静态变量global_Buffer+一个静态函数set_Global_Buffer (bufferType buffer);就可以解决所有的问题。
        既然有Buffer的存在那么肯定就有检查Buffer的机制了。对检查的机制进行一次修改。发现global_Buffer时添加上去就行了。就不需要额外花费一点时间去Loop所有的单位了。如果用第一个方法做的话,游戏在进行时很可能会出现顿卡,会严重影响用户(玩家)的体验。(例如THD,被顿卡吃操作,吃人头,吃机会,吃胜利无数次了……残念Q_Q)

        以上吧。=D
        • 静态成员变量我完全理解,就是静态成员函数不大理解。它干的活,普通成员函数或类外函数都能干。我没看到它存在的必要性,或者说优势吧。
          • 静态函数不需要对象。
            • 这个好像有点道理。可是,如果确实不需要对象,普通的类外函数不是就可以搞定?不过那样就破坏了类的封装性,从这个角度看,倒是确实有必要。看来主要应用还是操作静态变量,与我想象符合。
              • 当你只希望那个类在整个程序里是独有的时候,很有用。然后再把constructor往private下一藏..=D
      • 谢谢回复,这些我都理解.我的疑惑是:这些事情普通外部函数都可以做到,为什么非要把静态函数放到类中?静态函数又不能操作类的普通成员?
        • 权限问题。
          你做程序的时候。设置了一个变量。但这个变量不一定必须是Global变量。
          做程序有一个概念,就是:需要才知道。
          有必要你才给一个函数一个权限去修改那个东西。如果没有必要。那么就不要给。
          例如你有一个函数,调用时需要给他一个参数例如说:
          是整数。
          但是在使用时那个函数执行时不需要对提供的参数进行修改。那么你就可以把那个参数设为const。避免意外的修改。
          例如:
          function output_Value (const int value) // 因为这个函数不需要修改提供的变量,所以,就设置为常量。
          {
          std::cout<< value << std::endl;
          }
          或者某些人故意修改导致错误什么什么的……

          反正是安全、权限方面的问题……如果你不考虑安全方面的问题,你咋做都行……只要C++给你编译……
    • 最常见用法:用一个 class 放你 helper (static) methods, e.g.,: double d = Utilities.FahrenheitToCelsius(90); 另外 singleton 什么的... Is it what u were asking? 好处?一看 static 就知道是 stateless (除非访问一堆 static members)...
      • 第一个例子没太明白。singleton 确实是个好例子。我还没完整底学习过设计模式呐,得再看看书。谢谢。
        • 如果不太明白第一个例子,就先别急着看 design pattern。这么说吧,如果你写了个 method,IDE 发现你没有使用任何 instance members (and not even static members),IDE 会建议你将其 mark 成 static method,下次你一看到,就知道改变它影响的只是它自己(简化说法)。
          • 这回明白了。谢谢!还有一点疑惑:把这样的函数封装到类里面,是不是为了保证类的封装性?或者叫功能的完整性吧--等于是集成了一个通用功能到类的里面去。可是这样的功能与类分开有什么不好吗?比如STL里面,容器只保留基本功能,通用方法尽量设计成独立的。
            • 之前想回你的贴又忍住了,因为这个实在不是什么好东西。C++是multi-paradigm的语言,这是一个当时为吸引C程序员而不OO的又没有什么必要的设计。我感觉是C++设计的败笔之一。
              • 啊?败笔?不至于吧。C++兼容C,当然不能完全OO了。好像effective C++ 里面说过,C++其实是4种风格的语言。类的静态成员确实没有必要吗?至少静态数据成员还是很有必要的吧?谢谢
                • 这是我的想法,与你探讨。
                  1. C++不兼容C。不是所有C的程序都可以作为C++编译运行的。它的目标只是很象C,减少C程序员的学习障碍。

                  2. 类的静态成员函数,C里面没有。所以从上面的角度看,也多此一举。

                  3. C++不象Java,所有的函数必须依附于类。没有必要为工具函数指定个类,而且,类不是这么用的。参见,STL里algorithm库,这是C++的路子。上面,xml网友的例子,更象是Java和C#的思路。

                  4. 静态数据成员也没有必要的。什么时候你要用到静态数据成员?无非是变相定义一个全局变量。这也不是一个好的pattern,而且和3一样,在C++里更没有意义。

                  5. C++的设计路线是在C的基础上,添加OO的支持。既然,类是添加的OO部分,完全没有必要再用非OO的概念去污染类。这点是和Java之类程序的区别,因为在Java里,这些非OO的东西除了类外,无可依附。

                  6. Singleton本身也是一个不好的pattern。但是这个问题,扯远了,不深谈了。
                  • 没有不好的pattern, 只有被误用/滥用的 pattern....
                  • 只听说过C不兼容C++……还没听说过C++不兼容C……我找到的古老的C的代码统统都能编译并运行……我用的是MSVS2010...
                    • 建议您先找本C++入门看看。
                  • 这两天一直在想这个问题,抱歉现在才来回复。和大家的讨论对我非常有启发,下面是我的想法。标题以你文中的标号为准。
                    (1)(2)我所说的C++兼容C,意思是C++中可以写C风格的代码。C++ 不一定就是OO,或者说C++里面也可以写面向过程的代码。当然这样是优点还是缺点另说。

                    (3)(5) 与我的想法有共通之处,我正是没有看到静态成员函数的必要性,才发起了这一贴。我们的一点分歧是:经过讨论,我觉得把工具函数集成到类里,还是可以接受的。当然思路上与OO的概念不吻合。

                    (4) 我觉得静态成员变量还是很有必要的。至少,它可以把“变相全局变量”限制在类里。还有,当某些资源被类的所有对象共享的时候,就是静态成员变量有用武之地的时候。这样的例子应该不少。

                    (6)Singleton我还没仔细研究过,等我研究下再讨论。
                    • 简单回复一下。
                      把工具函数集成到类里,我们的看法也是差不多的,就是很不OO。说回来,既然不是什么好东西,又不是C里原有,何必多次一举。STL里,没有把工具函数集成到类里,不是也很好吗?namespace就是为了归类用的。

                      把“变相全局变量”限制在类里,还有,当某些资源被类的所有对象共享的时候,有很多更好的办法。比如,简单的话,可以在构造的时候把共享的对象传入。不是说OO就处理不了这些情况,恰恰是OO的方法更好,而静态成员变量使得很多人没有使用正确的方法。举一些用静态成员变量的问题:初始化的时机,初始化的顺序,析构的问题,继承的类里静态成员变量构造和析构顺序的控制,如何测试,如何mock?

                      还有一点,C++的设计时间是在smalltalk之后,而更纯OO的smalltalk就没有静态成员的概念。Smalltalk里,类似的问题可以这样解决:类本身就是对象,就可以直接定义类的成员变量和函数。相对而言,避免或者减少了上述的问题。不过,即使这样,必须这样做的情况也非常少。

                      这是为什么我觉得C++引入静态成员是个败笔,还不如,跟着smalltalk的路子走。
                      • 老兄,看来我的程度比你差得太远。请教:构造的时候传入,是传入共享对象的指针或引用吗?其实,本帖是我编程的时候遇到的问题。对高手来说,应该非常简单,等我把问题写出来,请不吝赐教。谢谢
                        • 小马用汉语学习编程么?
                          俺从你的帖子学到了两个汉语单词:类和静态。
                          • 是啊,我出来的晚,在国内就学过一点。英文又比较差,看英文书进度太慢,一着急就把中文书抄起来了。你是全英文学的编程吧?
                  • 4的说法有点极端。自己工作的application范畴里没有用到不一定这个feature在所有的领域都没用。相反,很多领域里其实很依赖这些。比如说
                    You need to create a class for many users to use. Each instance of the class represents one user, but all the users share of a central local resource. However, the access to the resource must be serialized. In this case, critical section protection rely on some OS features such as mutex,semaphore or something else. Being the only user to this central resource, to encapsulate this critical section protection mechanism into this class, don't you think you can make use of some static members so that only 1 instance of the mutex/semaphore will be allocated for all the instances of the same class?

                    Please think about the use case. Many C++ development heavily rely on static members and functions. If you don't use it, it doesn't mean other people don't make use of this feature. On the contrary, many industries heavily rely on this feature. One example could be the hardware resource sharing in the performance critical areas such as military and industry applications...
                    • 你举的例子就是一个典型的错误。你可以换一个角度考虑一下,如果没有静态变量,用什么方法去实现,然后哪一种更好。所谓的senior程序员都应该熟知这些方法,我就不重复了。
                      只有没有alternative,才能算“rely on”吧。
                      • 我明白你的意思。如果在内存很紧张,performance十分严格的条件下,分开成两个类是不可取的。
                      • 咱举个最简单的例子。一个类的所有instance都需要命名,名字就起"class_a.0", "class_a.1", "class_a.2".....,命名的结尾是以0开始的序列号。不用static,不能依赖外部函数,但是一定要把这个序列号的功能封装进这个类(毕竟只有这个类用),你给我找个办法出来
                        如果你能找到,我这里拜你为师了,哈哈~~
          • 大概我还保持着面向过程设计的思路。完全的面向对象,所有的方法都是封装到类里面的,是这样吗?
            • 简单说,是的。我上面说的,只是把一堆相关的静态 procedure 给 group 起来,你还是需要给它们一个 class。但 static methods 用法远不仅如此而已。
              • 越来越清晰了。至少我看到了它存在的必要性。其他的应用还得慢慢学。再次感谢。
    • 静态成员函数和静态变量一样,等于是建立了一个公用指针,等于OO之后留了一个非OO的后门。就象dotnet也留了一个使用指针的后门。
      • 这个没想到,容我再想想。谢谢
    • 学C++的,关注一下刚出来的11版,有巨大的改变,据C++之父说,C++11就像完全是一个新的语言
      • 能不能简单介绍一下?谢谢。全新的?完料,又得从新学。可怜我老版还没学全呐。
        • 是比较坑爹,看了一下,加入了函数式编程的语法,其他的就不懂了,对C++不熟,只不过江湖上传闻变化巨大,到现在也没有编译器100%支持,微软VS2013支持一部分,完全支持C++11的编译器至少要到2015年吧,所以现在不用担心
    • A toy example:

      // toy.h

      class A

      {

      public:

      static A* create(char type);

      };

       

      class B : public A {};

       

      class C : public A {};

       

       

       

      // toy.cpp

      A* A::create(char type)

      {

        A *p = 0;

       

        switch(type) {

        case 'A':   p = new A();                    break;

        case 'B':   p = dynamic_cast<A*>(new B());  break;

        case 'C':   p = dynamic_cast<A*>(new C());  break;

        default:

          printf("What the heck?\n");

          break;

        }

       

        return p;

      }

       

       

      • 没想明白,首先create()一定要定义成静态吗?普通函数不可以吗?其次,这样设计岂不是把A和他的子类耦合到一起了?我水平太差,别笑话啊。
        • B and C are subclasses of A, so they are coupled with A by definition.
          'create' is a 'factory' method to build an object of class A or its subclasses. A factory class is usually used to build objects of other classes, this is the fundamental idea of factory pattern.

          Declaring function 'create' as non-static makes no sense if A has a pure virtual function. But, if A has a pure virtual function, my 'create' function has a bug, ha ha...
          • 介个。父类和子类肯定是高度耦合的,不过,俺赶脚设计时也是尽量降低耦合比较好。像这个例子,A要知道自己有哪些子类,岂不是耦合得太厉害了?以后万一增加一个子类,还要修改A 的create 方法。
            • ok. 也就是这个似A非A的函数知道A的子类而已,标准factory pattern 里整一堆factory class,个个知道A,B,C,耦合得岂不更厉害?呵呵。。。
              再说了,A,B,C本来就是耦合在一起的,如果这样做不是问题的话,用一个似A非A的函数去实例化这些类,并没有增添新的耦合。

              如果创建一个对象,逻辑很复杂,俺这么个简单的函数就不好用了,所以俺说这是个toy example.
              • 好吧。不过我仍然没看到静态成员函数的必要性。另外,这个例子还是不太好理解,一般设计的原则是只有最底层的类是可以实例化的,上层的尽量设计成纯虚类。如果A需要实例化,为什么不设计一个D,用它来代替A?
                这样工厂实例化的时候,是BCD,都是A的子类,这样的层次不是更清晰?也降低了耦合。
                • 也行。办法是多种多样的,看个人的取舍了。我不关心C++究竟应不应该保留这一feature. 不过,一个类的静态成员函数在这个类实例化之前就可以使用,这还是有点儿意思的。
                  一个类的静态成员函数跟非静态成员函数是不一样的,我想在底层实现上,静态成员函数会跟全局函数放在一起,非静态成员函数会放在一个表里。
                  • 恩,我只是好奇,似乎没看到必要性。可能就像那位说的,在OO里面留个后门,以备万一。
                    • 说点儿自己的理解,望科班儿的童鞋斧正:
                      class定义了object的layout, object包含着method的实现,为了使用method必须先创建一个object,这就是所谓的OO。

                      如果我想绕开object的创建,直接从class就能得到method,这好像就成了C++里面的static function.

                      再绕回来看OO,一个class包含data (member variable)和method(s),那好,我定义一个class,其member variables是函数指针,那么这个时候,数据和方法并没有本质区别,OO 似乎也就毫无优势可言,对不对?

                      functional programming 说一切都是函数,我觉得更有道理一些。要不咱这样,function也是一种object,可以动态创建。比方说,在C++里面,咱也可以new某个function,如何?
                      • 不是科班出身,俺先喷你一下:OO不是那么简单滴,还有多态性聂。
                        • OO is a simple concept, but with tremendous consequences. :-)
                      • 和你谈讨一下。
                        本文发表在 rolia.net 枫下论坛》class定义了object的layout, object包含着method的实现,为了使用method必须先创建一个object,这就是所谓的OO。
                        class定义的是object的type。“object包含着method的实现,为了使用method必须先创建一个object”,这个陈述不算严谨,但是也可以接受。不过,这不是OO,只是OO的一个特性。OO的关键是数据和method的结合和封装。

                        》如果我想绕开object的创建,直接从class就能得到method,这好像就成了C++里面的static function.
                        如果要绕开object,直接用C里的函数就好了,没必要在创建另一个ugly的非OO的方式。既然要绕开OO,又何必用什么OO里的class呢?加到class里面,无非给人一种封装的错觉,然后,每一本C++入门书都要花至少一章纠正这种错觉。

                        》再绕回来看OO,一个class包含data (member variable)和method(s),那好,我定义一个class,其member variables是函数指针,那么这个时候,数据和方法并没有本质区别,OO 似乎也就毫无优势可言,对不对?
                        不好意思,没看明白。

                        》functional programming 说一切都是函数,我觉得更有道理一些。要不咱这样,function也是一种object,可以动态创建。比方说,在C++里面,咱也可以new某个function,如何?
                        把function做为object,还是OO,不是functional programming。functional programming是把function作为first class citizen,比如Lisp。在C里面,如果用functional programming的paradigm的话,可以用函数指针。更多精彩文章及讨论,请光临枫下论坛 rolia.net
                        • 咱接着扯这些个理论:
                          本文发表在 rolia.net 枫下论坛》class定义了object的layout, object包含着method的实现,为了使用method必须先创建一个object,这就是所谓的OO。
                          class定义的是object的type。“object包含着method的实现,为了使用method必须先创建一个object”,这个陈述不算严谨,但是也可以接受。不过,这不是OO,只是OO的一个特性。OO的关键是数据和method的结合和封装。
                          》OO 说一切都是object, 然后又说object 包含data及操作这些data的methods.对于同样一组数据和方法,不同的人会写出不同数量的类,OO 的随意性可见是多么的大。

                          》如果我想绕开object的创建,直接从class就能得到method,这好像就成了C++里面的static function.
                          如果要绕开object,直接用C里的函数就好了,没必要在创建另一个ugly的非OO的方式。既然要绕开OO,又何必用什么OO里的class呢?加到class里面,无非给人一种封装的错觉,然后,每一本C++入门书都要花至少一章纠正这种错觉。
                          》C++支持的东西太多,让人有点儿迷惑。假如我把一个函数同时放在三种地方:一个以静态函数的形式放在多个class里面,一个全局函数,一个放在多个namespace里面,尽管函数体是一模一样的,我能否说它们是一样的呢?我不大清楚C++ compiler是怎样区别这些函数的,是简单实用name mangling, 或是自动添加不同的type涅,或者说想怎么实现就怎么实现,没啥标准。

                          》再绕回来看OO,一个class包含data (member variable)和method(s),那好,我定义一个class,其member variables是函数指针,那么这个时候,数据和方法并没有本质区别,OO 似乎也就毫无优势可言,对不对?
                          不好意思,没看明白。
                          》我想说的是数据和方法没有区别。

                          》functional programming 说一切都是函数,我觉得更有道理一些。要不咱这样,function也是一种object,可以动态创建。比方说,在C++里面,咱也可以new某个function,如何?
                          把function做为object,还是OO,不是functional programming。functional programming是把function作为first class citizen,比如Lisp。在C里面,如果用functional programming的paradigm的话,可以用函数指针。
                          》我想要的是在程序运行时,动态生成函数的多个copy,也就是说在程序运行当中一个函数的代码段可以被任意复制。


                          我觉得咱这是纯理论忽悠,跟实际应用相去甚远。更多精彩文章及讨论,请光临枫下论坛 rolia.net
        • I don't know what made the language designer (Bjarne Stroustrup?) choose static function of a class as a C++ feature, but I'm OK with this. I ever read a paper talking about using C in an OO way, that really opens my eyes.
      • This is not a good example of the static function. Bcoz
        本文发表在 rolia.net 枫下论坛In this code, class A is base class and yet it needs to know its child type B and C prior to its implementation of its own member Create()...

        A most common use of static function in my career will be the service modules that interface to operating systems. Many of the operating systems are written in C or similar language so static function provides them a fixed entry point when the service module needs to hook up with a thread or callback functions. There are many existing examples if you are developing OS or OS drivers.

        When you think of the word 'static', please think of something that all the instances of the class will share for their own use. For example, a system entry point, a system callback or something that is exclusively share among all the instances of the same class. Anyway, there are too many examples if you are developing OS or drivers, especially if it's RTOS or real-time system applications.

        BTW, I don't have any comments on what other Rolian developers here are writing about... Many of the OS and driver developers have already decouple the underlying resource sharing with all these techniques so that the application developers don't feel they are restricted by the underlying hardware or system when using the APIs provided above the abstraction layer. So in their career context, they believe what they concluded are 'truth' that can cover what others aspect of the computer science make decisions for others... But that's not something I would appreciate.

        If you want, you can think about how to implement a system callback that is shared among all the instances of the same class... That will lead you to a much better example of how to use 'static' in C++. And yet, I haven't told you the techniques to access the non-static members from a static callback, I will leave the question to all the readers if you are interested in this.

        Anyway, keep digging and keep coding... if you can find it, dig deeper :)更多精彩文章及讨论,请光临枫下论坛 rolia.net
        • I don't quite understand your question, here is my guess:

          class A

          {

          public:

            A()

            virtual ~A();

           

          public:

            void say_hi() { printf("Hello World!\n"); }

           

          public:

            static int call_back(A* a)

            {

              a->say_hi();

            }

          };

           

           

          • I can see the improvements. Yup, keep going along this path...
            • I am not sure about the goal to achieve, I'll stop here for now.
        • 受教了,谢谢。就是说主要的应用还是作为线程函数和回调函数喽。静态成员函数访问非静态成员?是不是用一个静态指针指向第一个对象,然后用一个链表把所有的对象串起来。通过这个指向第一个对象的静态指针,就可以遍历所有对象。
          • 别客气,都基础知识。不过要批评一下哈,你给的这个是很缺乏编程经验的方案,答案其实很简单。很多OS的编程虽然是用C,但是已经考虑到这个问题了。所以,请查一下一般接口的参数,比如注册线程/回调函数/中断函数的参数,以及这些函数本身的参数,应该很容易找到答案的
    • 这个好像有点道理:“静态成员函数存在的原因是什么呢?主要是在建立任何对象之前可用它来访问静态数据成员,普通函数不能实现此功能。”