有这么个情景,程序需要打开设备,而打开设备会失败。为了模拟这个情景,c++代码中写了个设备类,由于在进行其他操作之前需要先打开这个设备,所以这里要对类做点设计。经过查阅和分析,想了两种方法只调用一次就能够获得已经打开的设备对象。
一是二段构造,二是构造函数中抛异常。
原来的构造函数中只是对内部变量进行赋值,construct函数负责完成打开设备操作,另外还要有个init静态函数把构造函数和construct函数包起来。在操作中发现,二段构造中的new操作似乎是不可避免的,这就需要在主函数中加入delete操作。
#include2. 构造加异常#include //模拟用来打开设备的函数,可能会失败,代表一个可能会失败的操作 int open(HANDLE* handle) { srand(time(NULL)); int num = rand() % 100; if (num < 50) return 0; else return -1; } class Device { public: Device() { handle = NULL; } ~Device() { }; bool construct() {//二段构造,这里只打开设备 int ret = open(&handle); if (ret != 0) { std::cout << "open device fail" << " ret: " << ret << std::endl; return false; } std::cout << "open device success" << std::endl; return true; }; static Device* init()//二段构造 { Device* device = new Device();//这里的new看上去无法避免 if (device->construct() == false) { delete device; return nullptr; } return device; } private: HANDLE handle;//打开设备中往往有个句柄 }; int main(int argc, char* argv[]) { Device* dev = Device::init(); //这里是各种操作 delete dev;//要多加一个关闭的操作 system("pause"); } */
在构造函数中加入try catch的处理异常的方法。由于构造函数没有返回值,拿到的对象不一定是成功打开了设备,还需要对内部变量handle进行判断。
#include#include //模拟用来打开设备的函数,可能会失败,代表一个可能会失败的操作 int open(HANDLE* handle) { srand(time(NULL)); int num = rand() % 100; if (num < 50) return 0; else return -1; } class Device { public: Device() { handle = NULL; try {//这里加异常判断 int ret = open(&handle); if(ret !=0) throw std::string("can't open devicen"); } catch (const std::string& str) { std::cout << str << std::endl; } } ~Device() { }; private: HANDLE handle;//打开设备中往往有个句柄 }; int main(int argc, char* argv[]) { Device dev; //这里是各种操作 system("pause"); }
笔者还是更认可构造函数中加异常的操作,如果用二段操作,需要记得delete掉new出来的对象,这样就破坏了RAII。



