你可以在没有实例化的情况下阻止构造函数的调用吗?

时间:2016-12-22 14:31:08

标签: c++

我班级的简化片段:

class UpdatingSystem
/* when system is "unsafe" it marks this condition by instantiating an
UpdatingSystem item. While this item exists errors are handled in a 
particular way. When the UpdatingSystem item goes out of scope error
handling reverts to normal.*/
{
private:
static THREAD int updatingSystemCount_;

public:
UpdatingSystem(const char* caller){updatingSystemCount++};
~UpdatingSystem(){updatingSystemCount--};
};

这有效:

{
    UpdatingSystem tempUnsafe("Reason it's unsafe");
    // do stuff that requires the system be 'unsafe' 
} // Revert to safe when destructor runs

这不是:

{
    UpdatingSystem("Reason it's unsafe");
    // do stuff that requires the system be 'unsafe' 
} 

...因为被调用的构造函数会创建一个临时项,并且析构函数会立即运行,而系统应该是“安全的”。

编写第二个错误的版本很容易犯错误。 有没有办法在没有实例化的情况下阻止构造函数的这种调用?

4 个答案:

答案 0 :(得分:2)

  

有没有办法阻止构造函数的这种调用   实例

不,您无法控制用户实例化您的课程的方式。

或许更好的名称会鼓励正确使用,例如:

class SystemUpdateGuard {..}

{
    SystemUpdateGuard guard_system_update("Reason it's unsafe");
    // do stuff that requires the system be 'unsafe' 
} // Revert to safe when destructor runs

答案 1 :(得分:1)

如果你明确想要禁止临时工,你可以做一些诡计。

制作UpdatingSystem的构造函数private,创建一个只接受对unique_ptr<UpdatingSystem>的引用的工厂类。这样它需要一个左值,并且由于智能指针,一旦超出范围,对象将被销毁,like

#include <iostream>
#include <memory>

class UpdatingSystem
{
    friend class UpdatingSystemFactory;
    public:
    ~UpdatingSystem() { std::cout << "destructor UpdatingSystem"; }
    private:
    UpdatingSystem() { std::cout << "constructor UpdatingSystem";}
};

class UpdatingSystemFactory
{
    public:
    static void GenerateUpdatingSystem(std::unique_ptr<UpdatingSystem>& ptr)
    {
        ptr = std::unique_ptr<UpdatingSystem>(new UpdatingSystem());
    }
};

int main() 
{
    //..when having to create an updating system:
    {
      std::unique_ptr<UpdatingSystem> tmp;
      UpdatingSystemFactory::GenerateUpdatingSystem(tmp);
    }
    return 0;
}

答案 2 :(得分:1)

这样的警卫怎么样:

...
UpdatingSystem(const char* caller, std::function<void()> func)
{
    updatingSystemCount++;
    f();
    updatingSystemCount--;
};
...

UpdatingSystem("whatever", [&](){ do_unsafe_stuff(); });

答案 3 :(得分:0)

这是一个架构问题。

可悲的是,唯一的解决方案是修改不安全的功能。它们必须要求UpdatingSystem对象。

最后,您的代码应如下所示......

var result = tcpclnt.BeginConnect(User.IP, User.Port, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3)); // Connect with timeout

if (!success)
{
    return "Failed to connect!";
}
Stream stm = tcpclnt.GetStream(); // get the stream

UTF8Encoding asen = new UTF8Encoding();

byte[] ba = asen.GetBytes(msg); // get the bytes of the message we are sending
byte[] intBytes = BitConverter.GetBytes(ba.Length); // Get the length of that in bytes
if (BitConverter.IsLittleEndian)
{
    Array.Reverse(intBytes);
}

stm.Write(intBytes, 0, intBytes.Length); // Write the length in the stream!
stm.Flush(); // Clear the buffer!
stm.Write(ba, 0, ba.Length); // Write the message we are sending!

// If we have answers....
byte[] bb = new byte[10000];
int k = stm.Read(bb, 0, 10000);
string mmessage = Encoding.UTF8.GetString(bb, 0, k);
// If we have answers....


tcpclnt.Close(); // Close the socket

这可以解决您的问题,因为如果不先创建{ UpdatingSystem tempUnsafe("Reason it's unsafe"); unsafe_operation(tempUnsafe); safe_operation(); another_unsafe_operation(tempUnsafe, 42); } // Revert to safe when destructor runs 对象就无法执行不安全的操作。

更新不安全的函数很简单,只需传递一个引用即可。您甚至不需要对该对象做任何事情或复制它。

UpdatingSystem

这种方法通常也使程序员的生活更轻松,因为它是迫使他们正确处理不安全功能的唯一方法。

如果不可能&#39;以这种方式定义功能级别的安全性,您可能需要重新考虑程序的抽象。