【问题标题】:C++ implicitly calling a function When? and How?C ++隐式调用函数何时?如何?
【发布时间】:2009-10-01 17:28:29
【问题描述】:

我有几个问题。

所有函数都包含在类成员函数中吗?还是只有前面声明“朋友”的那些?

成员函数的意义在于它们不能被其他任何类访问对吗?

隐式调用和显式调用有什么区别?

哪些函数可以或不能被隐式调用?

我希望看到一个隐式和显式调用的例子。

编辑:感谢您提供的出色答案,有很多零碎的东西回答了我的问题,并感谢您提供书籍的链接。我会读它们。

【问题讨论】:

  • 辉,你似乎需要一个完整的C++教程,而不仅仅是一个答案。看看stackoverflow.com/questions/388242/…,我个人的建议是“Accelerated C++”。
  • 要么你想问什么,你的问题意味着什么。很抱歉,但我建议,如果您是 C++ 初学者,请阅读 C++ 基础知识。但我们始终欢迎您提出问题

标签: c++ theory


【解决方案1】:

阅读Thinking in C++ by Bruce Eckel。这是一本优秀、易读的电子书,可免费下载,并会回答您的所有问题。

【讨论】:

    【解决方案2】:

    构造函数、析构函数和operator type() 函数被隐式调用。

    【讨论】:

      【解决方案3】:

      所有函数都在一个类中吗 成员函数?或者只有那些 前面有声明“朋友”?

      Friend 函数不是成员函数。它们与常规全局函数的不同之处在于它们可以访问类的非公共区域。例如:

      class myclass
      {
          friend void fun(const myclass& obj);
          int x;
      };
      
      void fun(const myclass& obj)
      {
          std::cout << obj.x; // x is private member
      }
      

      一个和一个有什么区别 隐式和显式调用?

      当您使用() operator 调用函数时,它是显式调用。如果你不那样做,那就是隐含的。显式调用示例:

      fun();
      

      隐式调用示例:

      void someScope(){
          myclass myobject; // constructors called
      
      } // destructor of myobject is called before exiting the function
      ....
      myclass* mySecondObject = new myclass; // constructor called
      delete mySecondObject; // destructor called
      

      【讨论】:

        【解决方案4】:

        我认为阅读这个网站是一个好的开始:The C++ FAQ

        但是,给你一个简短的答案:在类定义中声明的所有函数和变量都是该类的成员。 “朋友”关键字具有特殊含义,与谁可以访问各种成员有关。

        访问权限由成员是否在类定义的公共、私有或受保护部分中声明。

        阅读 C++ 常见问题解答应该会让您很好地了解这些部分是如何组合在一起的。

        【讨论】:

          【解决方案5】:

          隐式调用函数和显式调用函数之间存在细微差别。考虑标准文档中的以下测试用例

          struct A { };
          void operator + (A, A);
          
          struct B {
            void operator + (B);
            void f ();
          };
          
          A a;
          void B::f() {
            operator+ (a,a); // ERROR – global operator hidden by member
            a + a; // OK – calls global operator+
          }
          

          第一个失败是因为你明确地给出了一个函数名称,并且名称将被“从里到外”查找:首先在函数中,然后在它的类中,然后在全局范围内。

          在第二个中,查找函数候选的工作方式不同:成员函数和非成员函数分两个阶段查找,并且在查找非成员函数时,成员函数被忽略,因此成员运算符不会隐藏第二种情况下的全局运算符。

          显式函数调用也永远不会选择内置运算符。例如,你不能做operator+(10, 12);。一般来说,我会说,总是更喜欢隐式函数调用。


          所有函数都在一个类的成员函数中吗?还是只有前面声明“朋友”的那些?

          正如其他人所说,友元函数不是包含声明的类的成员,即使函数也在声明中定义

          struct A {
              friend void f() {
                std::cout << "member of the global namespace" << std::endl;
              }
          
              void g() {
                std::cout << "member of class A" << std::endl;
              }
          };
          

          f 的词法范围是A - 这意味着您可以引用A 的(静态)成员或嵌套类型,而无需在其名称前加上A::


          对于特殊的成员函数,可以显式调用析构函数或赋值运算符,而不能显式调用构造函数。它们的调用是隐式的,并且是创建新对象的一部分。

          【讨论】:

            【解决方案6】:

            所有函数都包含在类成员函数中吗?这取决于你的意思 “里面”。您可以在类命名空间中定义独立(非成员)函数。 声明为“朋友”的函数是成员函数(如果是,则不需要将它们声明为朋友)。类定义中的非友元函数是成员函数。

            具有“公共”访问权限的成员函数可由其他类和独立函数访问。

            隐式函数调用经常出现在类型转换和对象构造的上下文中。这是example

            class BigBuffer
            {
            public:
             BigBuffer(int initialValue)
               { memset(buffer, initialValue, sizeof(buffer)); }
            private:
             char buffer[65536];
            };
            
            extern void Foo(const BigBuffer& o);
            
            void oops()
            {
             Foo(3);
            }
            

            Foo(3) 导致隐式调用 BigBuffer 构造函数以转换 将整数 3 转换为 Foo 函数所期望的 BigBuffer 对象。

            【讨论】:

              【解决方案7】:

              回答问题:

              类声明中的所有函数都是成员函数,除了那些标记为“朋友”的函数。这些是可以访问内部的其他类或函数 有问题的课程。

              成员函数是与类相关的函数。默认情况下它们是private,或者如果它们出现在private: 指示符之后,这意味着它们只能被类中的其他函数访问。其他访问修饰符是protected,这意味着它们可以被其他类函数和继承自该类的类中的函数访问,public,意味着它们对每个人来说都是公平的游戏。指定为friend 的类或函数可以访问privateprotected 数据和函数成员。

              我不知道你所说的隐式和显式是什么意思。一种可能的含义与 explicit 关键字有关,它可以应用于构造函数。

              在 Foo 类中,假设我声明

              Foo(int i);
              explicit Foo(const char * s);
              

              这意味着,如果我在某处提及 int 值,编译器可以将其视为 Foo,但为了将字符串视为值,我必须明确说明它,所以如果我有

              f(Foo f);
              

              在某处声明,然后

              f(1);
              f(Foo("foo"));
              

              是合法的调用,但是

              f("foo");
              

              不是。

              从您的问题的性质来看,我认为您需要一本好的 C++ 基础书籍。除了C++ FAQ Lite,我还推荐一个关于excellent C++ books 的StackOverflow 问题。您可以通过学习程序和在这里提出随机问题来学习,但这需要更长的时间,而且您会错过一些东西。

              【讨论】:

                【解决方案8】:

                显式意味着该函数只有在您在源代码中明确调用时才会被调用。

                这通常与构造函数一起使用,以防止编译器在创建临时对象或进行转换时使用特定的构造函数。

                例如:

                class FooA
                {
                public:
                   FooA();
                };
                
                class FooB
                {
                public:
                   FooB();
                   explicit FooB(const FooA &other);
                };
                

                现在假设你有这个功能:

                void MyFunc(FooB &var) { ... }
                

                还有这段代码

                void main()
                {
                   FooA bar;
                   MyFunc(bar);
                
                   FooB foo(bar);
                }
                

                通常,如果您没有“explicit”关键字,编译器将能够通过构造函数从 FooB 类型构造 FooA 类型。现在它会抱怨当你将它传递给 MyFunc() 时,它不知道如何从 fooB 生成 FooA。

                但是,它不会抱怨从 bar 构造 foo,因为您明确调用了它。

                【讨论】:

                  【解决方案9】:

                  不知道你所说的隐式和显式是什么意思...

                  默认情况下,类成员是私有的。添加友元规范允许另一个类访问私有成员。例如:

                  class A
                  {
                     void hidden();
                     friend class B;
                  };
                  
                  class B
                  {
                     void callIntoA( A& a )
                     {
                         a.hidden();
                     }
                  };
                  

                  或者,如果您想公开某些内容,您可以指定一个“public:”部分,如下所示:

                  class A
                  {
                      void hidden();
                  
                  public:
                      void notHidden();
                      void alsoNotHidden();
                  
                  private:
                      void alsoHidden();
                  };
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-02-24
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-11-02
                    • 1970-01-01
                    相关资源
                    最近更新 更多