【问题标题】:why private constructor prevents object creation C++为什么私有构造函数会阻止对象创建 C++
【发布时间】:2017-05-12 16:30:45
【问题描述】:

我一直读到私有构造函数会阻止对象创建。 我已经在单例模式中使用过它们,并且我知道如何在使用私有构造函数(使用静态方法等)时创建对象。 我知道构造函数是用来初始化对象的。

但我不明白是什么让私有构造函数阻止了对象的创建。 如果我的对象没有被初始化怎么办。我的意思是它应该扔一些垃圾,但为什么它会限制??

我已经检查了 stackoverflow 中的所有现有答案,但我没有得到确切的概念。

【问题讨论】:

    标签: c++ private-constructor


    【解决方案1】:

    要在 C++ 中创建对象,需要调用构造函数。如果需要调用的构造函数不可访问,则无法调用,也无法创建对象。

    private 构造函数的重点不是阻止对象构造。它是关于控制哪些代码可以访问构造函数,从而限制哪些代码创建一个对象,该对象是该类的一个实例。类的所有成员函数(static 或其他)以及类的所有声明的 friends(可能是单个函数或其他类)都可以访问 private 构造函数 - 因此其中任何一个都可以使用private 构造函数创建类的实例(假设构造函数已定义)。

    如果无法调用构造函数,则无法初始化对象。毕竟,构造函数的工作是初始化对象。但是如果构造函数不可访问,则无法构造对象,因此不可能有未初始化的对象。

    当然,没有什么可以阻止类拥有多个具有不同访问控制的构造函数(privateprotectedpublic)。 classpublic 构造函数可以通过任何代码使用该构造函数来构造。但任何使用private 构造函数的尝试(由非成员非friend)仍将被拒绝。因此,访问控制允许class(的开发者)对实例的构建方式进行某种程度的控制。

    不定义(即不实现)构造函数确实会阻止对象的构造。如果该构造函数是private,编译器将拒绝调用它的尝试(除非尝试创建实例的函数是成员或friend,如上所述)。对于类的成员和朋友,编译器将允许访问构造函数,但(在典型的编译后链接工具链中)链接器不会构建可执行文件,因为它无法解析对未定义函数的调用.使用标记构造函数private 而不定义它的技术是阻止代码构造类实例的常用方法(通过阻止代码编译或阻止它运行)。

    【讨论】:

    • 所以我理解对象和构造函数之间的关系是 1)我创建一个对象“ClassName obj” 2)这个声明调用类构造函数“ClassName()” 3)这个构造函数分配内存。这样就完成了对象创建过程。如果我的对象无法调用构造函数,则不会分配内存并且不会创建对象。我的理解正确吗? ——
    • 不完全。使用ClassName obj; 创建一个对象会调用一个不接受任何参数的构造函数——它可能是一个没有实际参数的构造函数 (ClassName::ClassName()) 或一个所有参数都具有默认值的构造函数(例如,在类定义中声明为 ClassName(int x = 0) )。对象(ClassName 的实例)的内存在调用构造函数之前分配,然后由构造函数初始化(松散地变成对象)。如果构造函数不可访问,则编译器不允许构造对象,因此代码将无法编译。
    【解决方案2】:

    类私有范围不会阻止类实例化,但实际上它限制了“谁”可以创建对象。

    它就像其他成员数据的私有范围,不能从外部访问,只能用于accessorsgetters 以及其他`friend函数和类:

    #include <iostream>
    using namespace std;
    
    class Foo
    {
        public:
            Foo(int x) : value(x){ cout << "Foo(int) public ctor" << endl;} // ctor
    
            void SetValue(int x) {value = x;}  // setter
            int  GetValue()const{return value;}// getter
    
        private:
            int value;
            Foo(){ cout << "Foo() private ctor" << endl;} // private ctor
    
            friend ostream& operator<<(ostream& out, Foo& rhs)
            {
                out << rhs.value;
                return out;
            }
            friend Foo* CreateObject();
    };
    
    Foo* CreateObject()
    {
        Foo* ptrFoo = new Foo;
        return ptrFoo;
    }
    
    
    int main ()
    {
    
        //Foo theFoo;     // error C2248: 'Foo::Foo' : cannot access private member declared in class 'Foo'
        Foo theFoo2(0); // ok
    //  cout << theFoo2.value << endl; // error C2248: 'value' : cannot access private member declared in class 'Foo'
        cout << theFoo2.GetValue() << endl; // ok
        cout << theFoo2 << endl;
    
        Foo* ptrFoo = CreateObject();
        ptrFoo->SetValue(7);
        cout << ptrFoo->GetValue() << endl;
    
    
        cout << endl;
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      说将构造函数标记为私有会阻止对象创建是不正确的。它所做的只是限制对象在类内的代码中创建,只有私有构造函数。您可以创建一个新对象,而其他人则不能。

      这对单例非常有效,因为它可以帮助您确保您的单例仍然是该类的唯一实例。

      【讨论】:

        【解决方案4】:

        因为你不能从类外部调用私有类方法,如果构造函数是私有的,这意味着你不能创建类的实例,因为创建对象需要调用构造函数。

        在这方面,构造函数与任何其他类方法没有什么不同。如果一个类方法是私有的,你已经明白你不能从类外调用它。并且由于必须调用构造函数来构造类的实例,使用私有构造函数。

        【讨论】:

        • 所以从上面所有的 cmets 中我了解到对象和构造函数之间的关系是 1)我创建了一个对象“ClassName obj” 2)这个声明调用了类构造函数“ClassName()” 3)这个构造函数分配内存。这样就完成了对象创建过程。如果我的对象无法调用构造函数,则不会分配内存并且不会创建对象。我的理解正确吗?
        【解决方案5】:

        C++ 不允许在不调用构造函数的情况下创建对象。而如果构造函数不可访问,则无法完成创建。对象的生命周期定义在构造函数和析构函数的调用之间。

        您当然可以分配原始内存并将其转换为指向对象类型的指针(就像在C 中所做的那样),但您不会拥有该类的对象。在调用构造函数将原始内存区域转换为对象表示之前,该内存区域不会正式包含对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-02-11
          • 1970-01-01
          • 2012-02-05
          • 2015-10-07
          • 2019-10-16
          相关资源
          最近更新 更多