我班级的简化片段:
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'
}
...因为被调用的构造函数会创建一个临时项,并且析构函数会立即运行,而系统应该是“安全的”。
编写第二个错误的版本很容易犯错误。 有没有办法在没有实例化的情况下阻止构造函数的这种调用?
答案 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;以这种方式定义功能级别的安全性,您可能需要重新考虑程序的抽象。