构造函数的访问顺序
(1) 子类创建对象时
当从父类派生一个子类并声明一个子类的对象时,它将先调用父类的构造函数,然后调用当前类的构造函数来创建对象;在释放子类对象时,先调用的是当前类的析构函数,然后是父类的析构函数。
下面简单用程序展示这一点:
Father.h
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout << "Create the Father!" <<endl;
}
~Father()
{
cout << "Release the Father!" <<endl;
}
};
class Son:public Father
{
public:
Son()
{
cout << "Create the Son!" <<endl;
}
~Son()
{
cout << "Release the Son!" << endl;
}
};
main.cpp
#include "Father.h"
int main()
{
Son s;
return 0;
}
运行结果:
(2) 定义一个基类类型的指针,调用子类的构造函数为其构建对象,当释放对象时,如果析构函数是虚函数,则先调用子类的析构函数,然后再调用父类的析构函数;如果不是析构函数,则只调用父类的析构函数。
含有虚函数的情况:
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout << "Create the Father!" <<endl;
}
virtual ~Father()
{
cout << "Release the Father!" <<endl;
}
};
class Son:public Father
{
public:
Son()
{
cout << "Create the Son!" <<endl;
}
~Son()
{
cout << "Release the Son!" << endl;
}
};
#include "Father.h"
int main()
{
Father *f = new Son(); // 定义基类指针,调用子类的构造函数
f->~Father();
return 0;
}
运行结果:
没有虚函数的情况:
#include <iostream>
using namespace std;
class Father
{
public:
Father()
{
cout << "Create the Father!" <<endl;
}
~Father()
{
cout << "Release the Father!" <<endl;
}
};
class Son:public Father
{
public:
Son()
{
cout << "Create the Son!" <<endl;
}
~Son()
{
cout << "Release the Son!" << endl;
}
};
运行结果:
练习: 开发一个程序,定义一个类,包含“商品”和“售价”两个成员变量,要求重载运算符"
#include <iostream>
using namespace std;
class Buy
{
public:
int goods;
float price;
friend ostream& operator <<(ostream& out,const Buy& buy)
{
out << "good:" << buy.goods << " " <<"price: "<< buy.price;
return out;
}
Buy(int m1,float m2)
{
goods = m1;
price = m2;
}
};
int main()
{
Buy b1(2,20.7);
cout << b1<<endl;;
}
运行结果:
总结:
此处使用友元,因为重载输出运算符第一个形参必须是ostream类,而成员函数的第一个形参是默认的(this指针),而本类又需要用到ostream类中属性,则需要friend。重载输入运算符也是同理。
同时,一般对于重载输出运算符,第二个形参一般是const,因为输出的一个类不需要更改它;
exp: ostream & operator << (ostream& out, const classT& obj)
而重载输入运算符的第二个形参,则必须是非const,否则无法赋值。
exp: istream & operator >> (istream& in, classT& obj )