公共新的私有构造函数

dor*_*ron 4 c++

当我尝试编译以下内容时:

#include <iostream>

class Test
{
public:
    void* operator new (size_t num);
    void operator delete (void* test);
    ~Test();
private:
    Test();
};

Test::Test()
{
    std::cout << "Constructing Test" << std::endl;
}

Test::~Test()
{
    std::cout << "Destroying Test" << std::endl;
}

void* Test::operator new (size_t num)
{
    ::new Test;
}

void Test::operator delete(void* test)
{
    ::delete(static_cast<Test*>(test));
}

int main()
{
    Test* test = new Test;
    delete test;
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

$ g++ -o test test.cpp
test.cpp: In function ‘int main()’:
test.cpp:14: error: ‘Test::Test()’ is private
test.cpp:36: error: within this context
Run Code Online (Sandbox Code Playgroud)

如果new是一个成员函数,为什么它不能调用私有构造函数?

编辑: 我的想法是创建一个只能使用完全标准语法在堆上实例化的类.我希望因为new是一个数据成员,它可以调用私有构造函数,但由于new不用于堆栈对象,所以不允许在堆栈上创建对象.

vil*_*pam 10

这是您可以执行的操作,以强制在堆上创建对象:

class Foo {
public:
    static Foo *Create() {
         return new Foo;
    }
private:
    Foo() {}
};
Run Code Online (Sandbox Code Playgroud)

然后当你使用它时:

Foo *foo = Foo::Create();
Run Code Online (Sandbox Code Playgroud)

您可能需要考虑返回shared_ptr而不是原始指针,以帮助确保删除对象.

这在技术上并不是你所要求的,但它是你表示你希望实现的......


Dav*_*eas 9

我认为你对它的作用有误解operator new.它不会创建对象,而是为对象分配内存.编译器将在调用new new后立即调用构造函数.

struct test {
   void * operator new( std::size_t size );
};
int main()
{
   test *p = new test;
   // compiler will translate this into:
   //
   // test *p = test::operator new( sizeof(test) );
   // new (static_cast<void*>(p)) test() !!! the constructor is private in this scope
}
Run Code Online (Sandbox Code Playgroud)

operator new的主要用法是使内存分配器与系统的默认分配器(通常是malloc)不同,它意味着返回一个未初始化的内存区域,编译器将在该区域内调用构造函数.但是,在写入新调用的作用域中分配内存调用构造函数(在本例中为main).

验收完毕后

未规范问题的完整解决方案:如何强制我的类用户在堆中实例化?是将构造函数设为私有并提供工厂函数,如其他一些答案所示(如villintehaspam所述).


小智 5

new不会调用构造函数 - 编译器会这样做,并且构造函数必须是可访问的.拿这个更简单的代码:

class A {
    A() {}
public:
    void * operator new( size_t x ) { return 0; }
};

int main() {
    A* a = new A;
}
Run Code Online (Sandbox Code Playgroud)

显然,new不会调用构造函数,但是如果编译它仍然会得到"私有构造函数"错误消息.

  • 那么,这是否以某种方式说明了为什么编译器无法调用私有构造函数? (2认同)