关闭

类中指针数据成员的处理

发表于:2012-10-15 10:00

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:rehongchen    来源:51Testing软件测试网采编

  一般而言,类中只含有内置类型时,只使用编译器提供的默认constructor函数、默认destructor和默认overloaded assignment operator(重载操作符)即可,但是一旦有了指针数据成员,具体的说是指向堆中的值的指针数据成员,就得另当别论了。

  由于编译器添加的默认函数都比较简单,对于比较简单的类而言,通常没有什么问题,但是当类中有数据成员指向堆中的值时,什么都需要程序员自己做了。

  “实践出真知”,现在拿出一个比较好的代码分析:

  这是一个简单的animal的类,只有两个数据成员,但其中又一个是string*类型的,它是我们讨论的对象。

//Heap Data Member
//Demonstrates an object with a dynamically allocated data member


#include <iostream>
#include <string>


using namespace std;


class Animal
{
public:&nbsp;
&nbsp; &nbsp; Animal(const string& name = "", int age = 0); &nbsp;
&nbsp; &nbsp; ~Animal(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<SPAN style="WHITE-SPACE: pre">    </SPAN> <SPAN style="WHITE-SPACE: pre"> </SPAN>//destructor prototype &nbsp;&nbsp;
&nbsp; &nbsp; Animal(const Animal& c); &nbsp; &nbsp;<SPAN style="WHITE-SPACE: pre">     </SPAN>//copy constructor prototype
&nbsp; &nbsp; Animal& Animal::operator=(const Animal& c); &nbsp;<SPAN style="WHITE-SPACE: pre"> </SPAN>//assignment operator&nbsp;
&nbsp; &nbsp; void Greet() const;&nbsp;


private:
&nbsp; &nbsp; string* m_pName;<SPAN style="WHITE-SPACE: pre"> </SPAN>//★要注意的关键&nbsp;
&nbsp; &nbsp; int m_Age;
};


Animal::Animal(const string& name, int age)
{
&nbsp; &nbsp; cout << "(构造函数被调用)\n";
&nbsp; &nbsp; m_pName = new string(name);<SPAN style="WHITE-SPACE: pre">  </SPAN>//另外分配内存空间&nbsp;
&nbsp; &nbsp; m_Age = age; &nbsp;
}


Animal::~Animal() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //手工定义析构函数的必要性&nbsp;
{
&nbsp; &nbsp; cout << "(析构函数被调用)\n";
&nbsp; &nbsp; delete m_pName;<SPAN style="WHITE-SPACE: pre">      </SPAN>//释放内存空间&nbsp;
}


Animal::Animal(const Animal& c) &nbsp; &nbsp; &nbsp; &nbsp;<SPAN style="WHITE-SPACE: pre"> </SPAN>//手工定义拷贝构造函数的必要性&nbsp;
{
&nbsp; &nbsp; cout << "(拷贝构造函数被调用)\n";
&nbsp; &nbsp; m_pName = new string(*(c.m_pName));<SPAN style="WHITE-SPACE: pre"> </SPAN>//实现“深拷贝”的关键&nbsp;
&nbsp; &nbsp; m_Age = c.m_Age;
}


Animal& Animal::operator=(const Animal& c) &nbsp;//手工定义操作符重载的必要性&nbsp;
{
&nbsp; &nbsp; cout << "(重载操作符被调用)\n";
&nbsp; &nbsp; if (this != &c)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; delete m_pName;//别忘了释放掉原先的内存
&nbsp; &nbsp; &nbsp; &nbsp; m_pName = new string(*(c.m_pName));
&nbsp; &nbsp; &nbsp; &nbsp; m_Age = c.m_Age;
&nbsp; &nbsp; }
&nbsp; &nbsp; return *this;
}


void Animal::Greet() const
{
&nbsp; &nbsp; &nbsp;cout << "你好,我叫" << *m_pName << " ,我今年" << m_Age << "岁了。 ";
&nbsp; &nbsp; &nbsp;cout << "&m_pName: " << cout << &m_pName << endl;
}


//声明3个测试函数&nbsp;
void testDestructor();
void testCopyConstructor(Animal aCopy);
void testAssignmentOp();


int main()
{
&nbsp; &nbsp; testDestructor();
&nbsp; &nbsp; cout << endl;
&nbsp; &nbsp;&nbsp;
&nbsp; &nbsp; Animal crit("Poochie", 5);
&nbsp; &nbsp; crit.Greet();
&nbsp; &nbsp; testCopyConstructor(crit);
&nbsp; &nbsp; crit.Greet();
&nbsp; &nbsp; cout << endl;
&nbsp; &nbsp;&nbsp;
&nbsp; &nbsp; testAssignmentOp();


&nbsp; &nbsp; return 0;
}


void testDestructor()
{
&nbsp; &nbsp; Animal toDestroy("Rover", 3);
&nbsp; &nbsp; toDestroy.Greet();
}<SPAN style="WHITE-SPACE: pre"> </SPAN>//运行结束时,toDestroy对象随即被销毁&nbsp;


void testCopyConstructor(Animal aCopy) &nbsp;//注:不是引用类型&nbsp;
{
&nbsp; &nbsp; aCopy.Greet();
}


void testAssignmentOp()
{
&nbsp; &nbsp; Animal ani1("ani1", 7);
&nbsp; &nbsp; Animal ani2("ani2", 9);
&nbsp; &nbsp; ani1 = ani2;
&nbsp; &nbsp; ani1.Greet(); &nbsp;
&nbsp; &nbsp; ani2.Greet();
&nbsp; &nbsp; cout << endl;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
&nbsp; &nbsp; Animal ani3("ani", 11);
&nbsp; &nbsp; ani3 = ani3;
&nbsp; &nbsp; ani3.Greet();
}

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号