1、今天呢遇到一个问题:
#defineMSG_FILENAME 1
struct TMSG_HEADER
{
char cMsgID;
TMSG_HEADER(char MsgID = INVALID_MSG)
: cMsgID(MsgID)
{
}
};
structTMSG_FILENAME :public TMSG_HEADER
{
char szFileName[256];
TMSG_FILENAME()
: TMSG_HEADER(MSG_FILENAME)
{
}
};
第二个结构体的构造函数的写法之前没有看见过,之前只在构造函数冒号后面初始化参数,并没有类名,后来请教同学才得以解答,在此表示感谢~
其实是这样的,在TMSG_FILENAME类的构造函数前导中,我们要给TMSG_HEADER类的构造函数传递参数,我们完成这一点的方式是-----使用它的类名调用基构造函数。
TMSG_FILENAME():TMSG_HEADER(MSG_FILENAME)
{
}
其实本例中在TMSG_FILENAME类的构造函数前导中,从语法上来讲,给TMSG_HEADER类的构造函数传递参数不是必须的,因为TMSG_HEADER有个默认缺省构造函数,但是从功能上讲是有用的。如果TMSG_HEADER的构造函数改成如下:
TMSG_HEADER(charMsgID ): cMsgID(MsgID)
{
}
则是必须的。
2、另外强调一点,构建的顺序非常重要,首先构建基类,然后构建派生类,如下所示:
structTMSG_FILELENGTH : public TMSG_HEADER
{
long lLength;
TMSG_FILELENGTH(long length)
: TMSG_HEADER(MSG_FILELENGTH),lLength(length)
{
}
};
3、前面讲了继承,是对象间重要的“is a”的关系,还有一种“has a”的关系是对象嵌入,构造函数与上面的写法类似,如下所示:
class Matter
{
public:
Matter(int id)
: _identifier(id)
{
}
~Matter()
{
}
PRivate:
const int _identifier;
};
class World
{
public:
World(int id)
: _identifier(id),
_matter(_identifier) //初始化嵌入体
{
}
~World()
{
}
private:
const int _identifier;
const Matter _matter; //Matter类型的嵌入对象
};
int main()
{
World smallWorld(3);
}
此例有意思的地方是World构造函数的前导:
World(int id)
: _identifier(id),_matter(_identifier) //初始化嵌入体
它首先初始化_identifier,然后初始化_matter。初始化某个对象意味着调用它的构造函数,Matter的构造函数需要一个整数,这是我们要传递的值,基于让_identifier成为常量的同样原因,我们也让_matter成为常量,它在World的生存期永远不会改变,它们在前导中初始化,而且永远不能改变,甚至不能被任何人访问。现在,我们感到奇怪的是初始化的顺序与前导中的初始化器顺序毫无关系。事实上,如果嵌入对象的构造函数不需要任何参数,它可以在前导中完全被忽略,如果不需要显示初始化,整个前导均可以完全被忽略。相反,初始化的规则是:数据成员按它们在类定义中的出现顺序进行初始化。
因为在World的定义中,_identifier出现在_matter之前,所以_identifier首先被初始化,这就是为什么我们可以在_matter 构造函数中使用它的值的原因。C++中嵌入体的顺序与语句的顺序同等重要。
第3部分文字大部分来自书籍,由于书籍是同学为我解答问题给我发的照片,所以我并不知道书籍名称,见谅见谅!如有不当,请告知~
2017.2.16 北京多云,心情不好也不坏。要拓宽学习深度与广度啊亲~
新闻热点
疑难解答
图片精选