在对象初始化之前在对象上运行的方法?

1 c++ initialization

#include <iostream>
using namespace std;

class Foo
{

public:

 Foo(): initialised(0)
 {
  cout << "Foo() gets called AFTER test() ?!" << endl;
 };

 Foo test()
 {
  cout << "initialised= " << initialised << " ?! - ";
  cout << "but I expect it to be 0 from the 'initialised(0)' initialiser on Foo()" << endl;
  cout << "this method test() is clearly working on an uninitialised object ?!" << endl;
  return Foo();
 }

 ~Foo()
 {};

private:

 int initialised;

};


int main()
{

 //SURE this is bad coding but it compiles and runs
 //I want my class to DETECT and THROW an error to prevent this type of coding
 //in other words how to catch it at run time and throw "not initialised" or something

 Foo foo=foo.test();

}
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 5

是的,它在一个尚未构造的对象上调用该函数,这是未定义的行为.你无法检测到它的可靠性.我认为你也不应该试图发现它.与例如在已删除的对象上调用函数相比,这可能是偶然发生的.试图捕捉所有可能的错误几乎是不可能的.声明的名称在其初始化程序中已经可见,用于其他有用的目的.考虑一下:

Type *t = (Type*)malloc(sizeof(*t)); 
Run Code Online (Sandbox Code Playgroud)

这是C编程中常见的习惯用法,它仍然适用于C++.

就个人而言,我喜欢Herb Sutter关于空引用(同样无效)的故事.要点是,不要试图保护语言明确禁止的情况,特别是在一般情况下不可能可靠地诊断.随着时间的推移,你会得到一个虚假的安全,这变得非常危险.相反,培养您对语言的理解和设计界面(避免原始指针......),以减少出错的可能性.

在C++中,同样在C语言中,许多情况并未明确禁止,而是未定义.部分原因是有些事情很难有效地部分诊断,因为未定义的行为允许实现为它设计替代行为而不是完全忽略它 - 现有编译器经常使用它.

例如,在上述情况下,任何实现都可以自由地抛出异常.还有其他情况同样是未定义的行为,这对于实现来说更难以有效诊断:在构造之前访问不同转换单元中的对象就是这样一个例子 - 这被称为静态初始化顺序fiasco.