这两天在看OSG的插件实现的源代码的过程中发现了一个让我比较纳闷的问题:比如在OBJ插件中,其实现的ReadWriterOBJ类的readNode函数,代码如下:
osgDB::ReaderWriter::ReadResult ReaderWriterOBJ::readNode(std::istream& fin, const Options* options) const
{
if (fin)
{
fin.imbue(std::locale::classic());
obj::Model model;
model.readOBJ(fin, options);
ObjOptionsStruct localOptions = parseOptions(options);
osg::Node* node = convertModelToSceneGraph(model, localOptions, options);
return node;
}
return ReadResult::FILE_NOT_HANDLED;
}
这个地方出现了一个现象:函数定义的返回类型和函数实际的返回类型不一致----这里函数定义的返回类型为osgDB::ReaderWriter::ReadResult,但是在实现中的实际返回类型却为Node*或者ReadResult中的一个枚举类型。
当时我看到这里就比较纳闷,ReadResult、Node、以及ReadResult内部的那个枚举类型之间没有共同的父类,如何做到类型的统一的呢?上了OSG群问了下,也是没有得到认真的回答,于是只有自己再认真看了看ReadResult的实现。
后来发现ReadResult实现了两个构造函数:
ReadResult(ReadStatus status=FILE_NOT_HANDLED):_status(status) {}
ReadResult(osg::Object* obj, ReadStatus status=FILE_LOADED):_status(status),_object(obj) {}
当时就猜想应该和它们有关,最后通过自己的测试代码和相关的资料的求证,的确是它们搞的鬼。(没系统学过编程果然细节上认识是不足的啊)
“在<<C++primer>>里有提到这个过程,函数返回对象首先会创建一个临时的类对象,该对象是由复制构造函数生成,参数是返回值。然后再调用复制构造函数初始化需要返回的新的对象”
简单讲,就是现在函数需要返回类型A,A有通过类型B和C来构造对象的构造函数,那么在函数返回A时,如果实现中的返回类型为B和C,那么该函数则内部调用A的这两个构造函数来实现A的构造,并返回给函数调用处。我们可以通过如下测试代码更清晰的看到本问题的情况。
<pre name="code" class="cpp">class testClass
{
private:
string testClassForm;
public:
testClass(string name):testClassForm("string"){cout<<"constructed from string"<<endl;}//采用string构造
testClass(int name):testClassForm("int"){cout<<"constructed from int"<<endl;}//采用int构造
void logInfo(){cout<<"class form is "<<testClassForm<<endl;}
};
testClass testFunc(int type)
{
switch(type)
{
case 0://用string来构造
{
string testStr="";
return testStr;//代码上返回string
}
case 1://用int来构造
{
int testInt=0;
return testInt;//代码上返回int
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
testClass classFromString=testFunc(0);
classFromString.logInfo();
testClass classFromInt=testFunc(1);
classFromInt.logInfo();
return 0;
}
输出为:
constructed from string
class form is string
constructed from int
class form is int
请按任意键继续. . .
从这里可清楚的看到,在代码层返回的类型与实际返回数据类型在return时的内部细节是构造函数的调用来统一的,但是很显然如果被返回的类有空参数值的构造函数,那么在testFunc函数中直接return是会报错的。