【问题标题】:When do we need a private constructor in C++?我们什么时候需要 C++ 中的私有构造函数?
【发布时间】:2011-09-27 22:48:06
【问题描述】:

我对 C++ 中的私有构造函数有疑问。如果构造函数是私有的,如何创建类的实例?

我们应该在类中有一个 getInstance() 方法吗?

【问题讨论】:

    标签: c++ constructor private


    【解决方案1】:

    如果创建私有构造函数,则需要在类中创建对象

    #include<iostream>
    //factory method
    using namespace std;
    class Test
    {
     private:
     Test(){
     cout<<"Object created"<<endl;
    }
    public:
        static Test* m1(){
            Test *t = new Test();
            return t;
        }
        void m2(){
            cout<<"m2-Test"<<endl;
        }
    };
    int main(){
     Test *t = Test::m1();
     t->m2();
     return 0;
    }
    

    【讨论】:

      【解决方案2】:

      C++ 中的私有构造函数可用于限制常量结构的对象创建。你可以在 enum 一样的范围内定义一个类似的常量:

      struct MathConst{
          static const uint8 ANG_180 = 180;
          static const uint8 ANG_90  = 90;
      
          private:
              MathConst(); // Restricting object creation
      };
      

      MathConst::ANG_180一样访问它。

      【讨论】:

      • 这个目的被命名空间打败了,你可以把struct换成命名空间,一切都会变得更干净。
      【解决方案3】:

      当您想要控制类的对象创建时,私有构造函数很有用。

      让我们在代码中尝试:

      #include <iostream>
      using namespace std;
      
      class aTestClass
      {
          aTestClass() ////////// Private constructor of this class
          {
              cout << "Object created\n";
          }
          public:
      
      };
      
      int main()
      {
          aTestClass a;
          aTestClass *anObject;
      }
      

      aTestClass a 行导致错误,因为该行间接尝试访问私有构造函数。注释掉这一行并运行程序。它运行得非常好。现在的问题是如何在这种情况下创建对象。让我们再写一个程序。

      #include <iostream>
      using namespace std;
      
      class aTestClass
      {
          aTestClass() ////////// Private constructor of this class
          {
              cout << "Object created\n";
          }
          public:
      
          aTestClass* getAnObject() ///// A public method create an object of this class and return the address of an object of that class
          {
              return (new aTestClass);
          }
      };
      
      int main()
      {
          //aTestClass a;
          aTestClass *anObject = NULL;
          anObject = anObject->getAnObject();
      }
      

      输出是

      Object created
      

      所以我们创建了一个包含私有构造函数的类的对象。

      使用这个概念来实现一个单例类

      【讨论】:

        【解决方案4】:

        private 构造函数有几种情况:

        1. 限制为除friends 之外的所有人创建对象;在这种情况下,所有构造函数都必须是 private

          class A
          {
          private:
             A () {}
          public:
             // other accessible methods
             friend class B;
          };
          
          class B
          {
          public:
             A* Create_A () { return new A; }  // creation rights only with `B`
          };
          
        2. 限制某些类型的构造函数(即复制构造函数、默认构造函数)。例如std::fstream 不允许通过这种无法访问的构造函数进行复制

          class A
          {
          public:
             A();
             A(int);
          private:
             A(const A&);  // C++03: Even `friend`s can't use this
             A(const A&) = delete;  // C++11: making `private` doesn't matter
          };
          
        3. 要有一个公共的委托构造函数,它不应该暴露给外部世界:

          class A
          {
          private: 
            int x_;
            A (const int x) : x_(x) {} // common delegate; but within limits of `A`
          public:
            A (const B& b) : A(b.x_) {}
            A (const C& c) : A(c.foo()) {}
          };
          
        4. 对于singleton patterns,当单例class 不可继承时(如果它是可继承的,则使用protected 构造函数)

          class Singleton
          {
          public:
             static Singleton& getInstance() {
                Singleton object; // lazy initialization or use `new` & null-check
                return object;
             }
          private:
             Singleton() {}  // make `protected` for further inheritance
             Singleton(const Singleton&);  // inaccessible
             Singleton& operator=(const Singleton&);  // inaccessible
          };
          

        【讨论】:

        • 实际上,如果该类是子类并且只能从子类中使用,它可能是protected static
        • 我不明白@larsm 评论的“赞成票”。没有意义。
        • @Alf:它不再是了,但在它说“必须是公共静态的”之前。
        • 在帖子中为每个案例提供示例会很棒。
        • 我认为万一(3)你想让复制构造函数是private,而不是public,对吧?
        【解决方案5】:

        私有构造函数通常与 Builder 方法一起使用,例如在 Named Constructor 习惯用法中。

        class Point
        {
        public:
          static Point Polar(double, double);
          static Point Cartesian(double, double);
        private:
          Point(double,double);
        };
        

        在这个(典型的)示例中,命名构造函数用于明确使用哪个坐标系来构建Point 对象。

        【讨论】:

        • 是的。一个详细的例子是可用的here
        • 这是我所知道的最常见的情况。 builder方法的另一个术语是静态工厂方法
        【解决方案6】:

        这取决于为什么首先将构造函数设为私有(您应该询问编写您正在编辑的类的人)。有时可以将构造函数设为私有以禁止复制构造(同时允许通过其他构造函数进行构造)。其他时候,可以将构造函数设为私有以禁止创建类,除非由类的“朋友”创建(如果该类是“助手”,只能由助手类所针对的类使用,则通常会这样做。已创建)。也可以将构造函数设为私有以强制使用(通常是静态的)创建函数。

        【讨论】:

          【解决方案7】:

          如果某个构造函数是私有的,这意味着除了类本身(和朋友)之外,没有人应该能够使用该构造函数创建它的实例。因此,您可以提供像 getInstance() 这样的静态方法来创建类的实例,或者在某个朋友类/方法中创建实例。

          【讨论】:

            【解决方案8】:

            是的,这通常用在Singleton pattern中,通过静态成员函数访问对象。

            【讨论】:

              猜你喜欢
              • 2011-02-04
              • 2011-03-30
              • 1970-01-01
              • 2023-04-09
              • 2021-10-15
              • 2019-10-16
              相关资源
              最近更新 更多