有一个带有几个整数和一个指针的类,
class A {
int a;
int b;
char* s;
public:
...
class ConstructA {
A &a;
public:
ConstructA (A& ta) : a(ta) {}
...
};
};
如上所见,ConstructA负责构建对象A. 我想编写一个方法来查看ConstructA是否成功构造了对象a。你会怎么做呢?
答案 0 :(得分:7)
由于构造函数无法在C ++中失败,因此对象可以是:
如果构造函数抛出异常,则在捕获异常时该对象实际上不存在。
您可能希望实现一个额外的方法,例如isOK()
,它返回对象的内部状态是否表示有用的东西。例如,如果您有一个表示文件的对象,则可以使用isOK()
表示该文件可以成功打开。但是,就C ++而言,无论文件是否可以打开,文件对象都将完全构建。
话虽如此,我并不完全确定ConstructA
类在你的例子中的作用。
答案 1 :(得分:0)
作为一般规则,如果构造中存在任何失败,您将获得抛出异常 - 来自对象本身的特定于程序的异常,或者来自运行时的内存异常或类似内容。
在这种特殊情况下,您没有构建类型为A的对象,而是要初始化引用。所以没有任何建筑有失败的机会。
(也许关于你想要完成什么的更多细节可以帮助有人给出更好的答案?)
答案 2 :(得分:0)
首先,你的ConstructA课对我来说毫无意义。基本上确实有两种情况:
我将在下面的代码中使用您的ConstructA,以便指出有关构造失败的信号:
A a0;
try {
A::ConstructA a1(a0);
} catch(...) {
// fail to construct a1
}
构造函数抛出异常以在其构造失败时发出信号。 这个想法是,如果一个对象的构造失败,那么就不会构造该对象。换句话说,该对象不存在。如果你必须在构造函数初始化列表中初始化a1,那么也有一种方法:
struct B {
B() try : a1(a0) {
// other constructor code...
} catch(...) {
// fail to construct either a0 or a1, or constructor
// code threw
}
A a0;
A::ConstructA a1;
};
try {
B b;
} catch(...) {
// fail to construct B
}
首先,执行构造函数的catch块中的代码,然后将异常自动传播到创建B对象的代码,并考虑其catch块。
您的类ConstructA的构造函数可能如下所示,例如:
struct ConstructA {
ConstructA(A &a):a(a) {
if(!condition_met) {
throw std::runtime_error("condition_met false");
}
}
A &a;
};
具有文件流对象但未连接到文件的情况就是如此。如果在构造函数中发现提到的文件不存在,您仍然可以完全构造流,但将其设置为 not-opened 状态。某些操作可能会被禁止,您可以使用isOpen
或isValid
函数来查询对象的状态。
这也适用于其他情况。我使用的一些框架有一个Color
类。默认构造一个颜色类使其处于无效状态,因此它不会与任何有效颜色相等:
Color c;
assert(c.isValid() == false);
相同的技术用于空指针。当您为其分配 NULL 时,它被设置为已定义但受限制的状态:
int *a = NULL;
assert(a == NULL);
例如,您不能取消引用空指针。
答案 3 :(得分:0)
你是ConstructA只是试图抓住已经构建的A的引用,尝试将其改为:
class ConstructA {
A a; // Don't make this a reference
public:
ConstructA (A& ta) : a(ta) {}
...
};
答案 4 :(得分:-2)
mkal,我总是建议人们不要在C ++中使用异常。它会导致更多问题,试图解决。
要回答你的问题,为了避免C ++中的异常,你可能会减少你的工作量 想在你的构造函数中做,并创建一个init()方法,如果出现问题则返回错误代码。
基本上,无论你在C ++构造函数中做什么,它都必须成功。
希望有所帮助。