我们什么时候需要 C++ 中的私有构造函数?

发布于 2024-11-18 14:16:23 字数 88 浏览 3 评论 0原文

我有一个关于 C++ 中的私有构造函数的问题。如果构造函数是私有的,我如何创建该类的实例?

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

I have a question about private constructors in C++. If the constructor is private, how can I create an instance of the class?

Should we have a getInstance() method inside the class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

吃颗糖壮壮胆 2024-11-25 14:16:23

有一些使用 private 构造函数的场景:

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

    <前><代码>A类
    {
    私人的:
    一个 () {}
    民众:
    // 其他可访问的方法
    朋友B级;
    };

    B级
    {
    民众:
    A* Create_A () { 返回新的 A; } // 仅具有“B”的创建权限
    };

  2. 限制某些类型的构造函数(即复制构造函数、默认构造函数)。例如 std::fstream 不允许通过这种不可访问的构造函数进行复制

    <前><代码>A类
    {
    民众:
    一个();
    A(整数);
    私人的:
    A(const A&); // C++03: 即使是“朋友”也不能使用这个
    A(const A&) = 删除; // C++11:设置 `private` 并不重要
    };

  3. 要拥有一个公共的委托构造函数,该构造函数不应暴露给外部世界:

    <前><代码>A类
    {
    私人的:
    整数x_;
    A (const int x) : x_(x) {} // 公共委托;但在“A”的范围内
    民众:
    A (const B& b) : A(b.x_) {}
    A (const C& c) : A(c.foo()) {}
    };

  4. For 单例模式,当单例不可继承时(如果可继承,则使用受保护的构造函数)

    类单例
    {
    民众:
       静态单例&获取实例(){
          单例对象; // 延迟初始化或使用 `new` &空检查
          返回对象;
       }
    私人的:
       Singleton() {} // 为进一步继承设置“protected”
       Singleton(const Singleton&); // 无法访问
       辛格尔顿&运算符=(const Singleton&); // 无法访问
    };
    

There are a few scenarios for having private constructors:

  1. Restricting object creation for all but friends; in this case all constructors have to be 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. Restricting certain type of constructor (i.e. copy constructor, default constructor). e.g. std::fstream doesn't allow copying by such inaccessible constructor

    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. To have a common delegate constructor, which is not supposed to be exposed to the outer world:

    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. For singleton patterns when the singleton class is not inheritible (if it's inheritible then use a protected constructor)

    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
    };
    
装迷糊 2024-11-25 14:16:23

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

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

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

A private constructor is commonly used with Builder methods, for example in the Named Constructor idiom.

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

In this (typical) example, the Named Constructor idiom is used to make it explicitly which coordinate system is used to build the Point object.

揽清风入怀 2024-11-25 14:16:23

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

让我们尝试一下代码:

#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

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

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

A private constructor is useful when you want to control the object creation of a class.

Let’s try in code:

#include <iostream>
using namespace std;

class aTestClass
{
    aTestClass() ////////// Private constructor of this class
    {
        cout << "Object created\n";
    }
    public:

};

int main()
{
    aTestClass a;
    aTestClass *anObject;
}

The line aTestClass a causes an error because this line is indirectly trying to access the private constructor. Comment out this line and run the program. It runs absolutely fine. Now the question is how to create the object in a such case. Let's write another program.

#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();
}

The output is

Object created

so we have created an object of the class containing a private constructor.

Use this concept to implement a singleton class

撧情箌佬 2024-11-25 14:16:23

是的,这通常用在通过静态成员函数访问对象的单例模式中。

Yes, this is commonly used in the Singleton pattern where the object is accessed through a static member function.

浅唱々樱花落 2024-11-25 14:16:23

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

If some constructor is private, it means that no one but the class itself (and friends) should be able to create instances of it using that constructor. Therefore, you can provide static methods like getInstance() to create instances of the class or create the instances in some friend class/method.

云朵有点甜 2024-11-25 14:16:23

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

It depends on why the constructor was made private in the first place (you should ask whoever wrote the class you are editing). Sometimes a constructor may be made private to disallow copy construction (while allowing construction through some other constructor). Other times a constructor may be made private to disallow creating the class except by the class's "friend"s (this is commonly done if the class is a "helper" that should only be used by the class(es) for which the helper class was created). A constructor may also be made private to force the use of a (usually static) creation function.

耳根太软 2024-11-25 14:16:23

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

#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;
}

If you create a private constructor you need to create the object inside the class

#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;
}
瞎闹 2024-11-25 14:16:23

C++ 中的私有构造函数可用于限制常量结构的对象创建。您可以在相同范围内定义类似的常量,如枚举:

struct MathConst{
    static const uint8 ANG_180 = 180;
    static const uint8 ANG_90  = 90;

    private:
        MathConst(); // Restricting object creation
};

MathConst::ANG_180 一样访问它。

A private constructor in C++ can be used for restricting object creation of a constant structure. And you can define a similar constant in the same scope like enum:

struct MathConst{
    static const uint8 ANG_180 = 180;
    static const uint8 ANG_90  = 90;

    private:
        MathConst(); // Restricting object creation
};

Access it like MathConst::ANG_180.

烟酒忠诚 2024-11-25 14:16:23

我将它与返回 std::Optional 的 friend 函数结合使用,以便安全地构造对象,同时避免异常。例如:

#include <optional>

class Object {
private:
    Object(...) { /* ... */ }

    friend std::optional<Object> make_object(...);
};

std::optional<Object> make_object(...)
{
    // ...
    if (error)
        return std::nullopt;

    // else
    return std::make_optional<Object>(...);
}

并像这样使用它:

bool f()
{
    auto opt_obj = make_object(...);
    if (!opt_obj)
        return false;

    // else
    auto obj = *std::move(opt_obj);  // API magic

    // ...

    return true;
}

I use it in combination with friend function(s) returning std::optional in order to safely construct objects while avoiding exceptions. For example:

#include <optional>

class Object {
private:
    Object(...) { /* ... */ }

    friend std::optional<Object> make_object(...);
};

std::optional<Object> make_object(...)
{
    // ...
    if (error)
        return std::nullopt;

    // else
    return std::make_optional<Object>(...);
}

And using it like:

bool f()
{
    auto opt_obj = make_object(...);
    if (!opt_obj)
        return false;

    // else
    auto obj = *std::move(opt_obj);  // API magic

    // ...

    return true;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文