指向具有私有构造函数的类的类成员的指针

Posted

技术标签:

【中文标题】指向具有私有构造函数的类的类成员的指针【英文标题】:Pointers to Class Members into a class with a private constructor 【发布时间】:2020-11-08 22:54:21 【问题描述】:

假设我有一个带有私有构造函数的类,该类将用于表示单个对象。假设我有一些非静态成员,我想在不使用范围解析运算符的情况下访问它们。我注意到我可以通过创建指向类类型的指针来实现这一点。我想知道为什么即使默认构造函数是私有的,我也可以声明指向该类的指针?这是一个示例程序。


// Example program
#include <iostream>
#include <string>


class OnlyOne
    public:
    void Location()
        std::cout<<10<<std::endl;
        
    
    private:
    OnlyOne();
;
int main()

    //does not work Location() is not a static member
    //OnlyOne::Location();
     
      // doesn't work because default constructor is private.
     //OnlyOne one;
    //one.Location();
    
    
    OnlyOne* two=nullptr;
    two->Location();


我一直在网上寻找是否可以找到答案,但无法获得我想要的东西。

【问题讨论】:

您可以声明甚至没有构造函数的类型的指针,例如联合。声明一个指针是一回事,但实例化是另一回事。 注意:您可能会发现OnlyOne* two=nullptr; two-&gt;Location(); 似乎按预期运行。 undefined behaviour 几乎无限可能的表现之一是预期的行为。真正讨厌的东西,UB,因为很容易证明你拥有它,而很难证明你没有。在这种情况下,Location 不使用调用它的 OnlyOne,从不使用 this,因此程序可能永远不会注意到有一个错误的 this 如果我理解正确,Ali Askari 给出的解决方案通过使用单例模式解决了这个问题。 【参考方案1】:

当您声明某种类型的指针时,该类型不必是可构造的。事实上,这种类型甚至不必是完整的。所以,这一行:

OnlyOne* two = nullptr;

完全没问题。

注意这一行:

two->Location();

调用未定义的行为,因为two 没有指向任何对象,因此没有可以调用Location 成员函数的对象。

事实上,由于这种类型是不可构造的,two 永远不能指向一个有效的对象。你必须提供一种方法来构造这样一个对象,或者通过提供一个公共构造函数,或者通过一个静态成员函数来构造并返回这样一个对象。

【讨论】:

如果我将 void location() 更改为 OnlyOne* Location() 并返回返回 (OnlyOne*)10? 的语句 这将允许您返回OnlyOne*,但如果没有有效的OnlyOne 实例,您首先不能调用Location。另请注意,return (OnlyOne*)10 对编译器撒谎。如果您对编译器撒谎以消除编译器错误,那么您所做的就是将错误从编译时移到运行时,这样可能更难找到。您需要一个有效的OnlyOne,而地址 10 几乎可以肯定不包含OnlyOne【参考方案2】:

您可以使用单例 pttern 来实现具有私有构造函数的类:


// Example program
#include <iostream>
#include <string>


class OnlyOne
    public:

    static OnlyOne* instance() 
        static OnlyOne obj;
        return &obj;
    

    void Location()
        std::cout<<10<<std::endl;
        
    
    private:
    OnlyOne()  
;
int main()

    //does not work Location() is not a static member
    //OnlyOne::Location();
     
      // doesn't work because default constructor is private.
     //OnlyOne one;
    //one.Location();
    
    
    OnlyOne* two=OnlyOne::instance();
    two->Location();

【讨论】:

以上是关于指向具有私有构造函数的类的类成员的指针的主要内容,如果未能解决你的问题,请参考以下文章

具有引用数据成员的类的默认构造函数?

序列化指向没有默认构造函数的类的指针时无法覆盖 save_construct_data

含有指针变量的类需要重写拷贝构造函数,拷贝赋值函数,析构函数

是否可以定义指向构造函数的函数指针?

具有私有构造函数和析构函数的类对象的向量?

如何获得指向类的复制构造函数的成员函数指针?