您的位置:首页 > 其它

子类的构造,析构和拷贝

2017-08-07 11:25 134 查看

子类的构造函数

一.隐式构造基类

•如果子类的构造函数没有显式指明其基类部分的构造方式,那么编译器会选择其基类的缺省构造函数,构造该子类对象中的基类子对象

–class Student : public Human
{
public: Student (int no) : m_no (no) {}
};


•但是请注意,只有在为基类显式提供一个无参构造函数,或者不提供任何构造函数(系统会提供一个缺省的无参构造函数)的情况下,基类才拥有无参构造函数

二.显式构造基类

•子类的构造函数可以在初始化表中显式指明其基类部分的构造方式,即通过其基类的特定构造函数,构造该子类对象中的基类子对象

–class Human
{
public: Human (string const& name, int age) : m_name (name), m_age (age) {}
};


–class Student : public Human
{
public: Student (string const& name, int age, int no) : Human (name, age), m_no (no) {}
};


三.子类对象的构造过程

•子类的构造函数执行如下步骤:

–首先,按照继承表的顺序,依次调用各个基类的构造函数,构造子类对象中的基类子对象

–其次,按照声明的顺序,依次调用各个类类型成员变量相应类型的构造函数,构造子类对象中的成员子对象

–最后,执行子类构造函数体中的代码,完成整个构造过程

•无论如何,子类的构造函数都一定会(显式或隐式地)调用其基类和类类型成员变量类型的构造函数

子类的析构函数

一.子类负责析构基类

•子类的析构函数,无论是自己定义的(自定义析构函数)还是系统提供的(缺省析构函数),在执行完其中的析构代码,

并析构完所有的类类型成员子对象以后,会自动调用其基类的析构函数,析构该子类对象中的基类子对象

–class Human { ... };

–class Student : public Human
{
public: ~Student (void) { ... /* ~Human () */ }
};

–Student* student = new Student (...);
delete student;


二.基类不会析构子类

•对一个指向子类对象的基类指针使用delete运算符,实际被调用的将是基类的析构函数,该函数不会调用子类的析构函数,

其所析构的仅仅是子类对象中的基类子对象,而子类的扩展部分极有可能因此而形成内存泄漏

–class Human
{
public: ~Human (void) { ... }
};

–class Student : public Human { ... };

–Human* human = new Student (...);
delete human;


三.子类对象的析构过程

•子类的析构函数执行如下步骤:

–首先,执行子类析构函数体中的代码,析构子类的扩展部分

–其次,按照声明的逆序,依次调用各个类类型成员变量相应类型的析构函数,析构子类对象中的成员子对象

–最后,按照继承表的逆序,依次调用各个基类的析构函数,析构子类对象中的基类子对象,完成整个析构过程

•无论如何,子类的析构函数都一定会隐式地调用其类类型成员变量类型和基类的析构函数

子类的拷贝构造

一.缺省全拷贝

•如果子类没有定义拷贝构造函数,那么编译器为子类提供的缺省拷贝构造函数,会自动调用其基类的(自定义或缺省)拷贝构造函数,拷贝构造子类对象中的基类子对象

–class Student : public Human
{
public:
Student (String const& name, int age, int no) :
Human (name, age), m_no (no) {}
/*
Student (Student const& that) : Human (that) { ... }
*/
};


二.自定义局部拷贝

•如果子类定义了拷贝构造函数,但没有显式指明以拷贝方式构造其基类部分,那么编译器会选择其基类的缺省构造函数,构造子类对象中的基类子对象

–class Student : public Human
{
public:
Student (String const& name, int age, int no) :
Human (name, age), m_no (no){}
Student (Student const& that) : /* Human (), */ m_no (that.m_no) {}
};


三.自定义全拷贝

•如果子类定义了拷贝构造函数,同时显式指明了其基类部分以拷贝方式构造,那么子类对象中的基类部分和扩展部分将一起被复制

–class Student : public Human
{
public:
Student (String const& name, int age, int no) :
Human (name, age), m_no (no) {}
Student (Student const& that) : Human (that), m_no (that.m_no) {}
};


子类的拷贝赋值

一.缺省全赋值

•如果子类没有定义拷贝赋值运算符函数,那么编译器为子类提供的缺省拷贝赋值运算符函数,会自动调用其基类的(自定义或缺省)拷贝赋值运算符函数,复制子类对象中的基类子对象

–class Student : public Human
{
/*
Student& operator= (Student const& rhs) { ... Human::operator= (rhs) ... }
*/
};


二.自定义局部赋值

•如果子类定义了拷贝赋值运算符函数,但没有显式调用其基类的拷贝赋值运算符函数,那么子类对象中的基类子对象将因得不到复制而保持原状

–class Student : public Human
{
public: Student& operator= (Student const& rhs)
{
if (&rhs != this)
m_no = rhs.m_no;
return *this;
}
};


三.自定义全赋值

•如果子类定义了拷贝赋值运算符函数,同时显式调用了其基类的拷贝赋值运算符函数,那么子类对象中的基类部分和扩展部分将一起被复制

–class Student : public Human
{
public: Student& operator= (Student const& rhs)
{
if (&rhs != this)
{
Human::operator= (rhs);
m_no = rhs.m_no;
}
return *this;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息