// 我把你的代码做了些修改
#include <iostream>
class Father
{
protected:
int m_father;
public:
Father();
Father(int n);
int GetInt(){return m_father;} //获得m_father
};
class Son: public Father
{
private:
double m_son;
public:
Son();
Son(double x,int n);
double GetDouble(){return m_son;} //获得m_son
};
Father::Father()
{
std::cout<<"基类默认构造函数被调用"<<std::endl;
m_father=0;
}
Father::Father(int n)
{
std::cout<<"基类int形参构造函数被调用"<<std::endl;
m_father=n;
}
Son::Son()
{
std::cout<<"子类默认构造函数被调用"<<std::endl;
m_son=0;
}
Son::Son(double x,int n):Father(n) // 这样写
{
std::cout<<"子类int形参构造函数被调用"<<std::endl;
m_son=x;
// Father::Father(n);//测试发现,这句话好像只是建立了一个临时的
//基类对象,子类构造函数返回后什么都没有发生
}
int main()
{
Son a(44,3);
std::cout<<"子类中继承的基类变量m_father为:"<<aGetInt()<<std::endl;
std::cout<<"子类中量m_son为:"<<aGetDouble()<<std::endl;
return 0;
}
//用指针即可
Child bd[100];//定义100个子类对象指针,因为没有指针没有初始化,所以不会调用构造函数
for( int i=0; i<100; i++ )
{
bd[i] = new Child( a, b, c ); //使用new会调用构造函数给子类或父类赋值
}
//记得delete对象, 堆区内存的释放要靠自己
记住:对象只是一段内存。它可能属于多个类。即使那个类是一个抽象类。
子类对象的内存结构里包含了父类的数据成员。那么这段内存能不能称作父类的对象呢?当然可以了。
好比一个活生生(表示被实例化了)的程序员(programmer类)jack(对象名)是一个人(person类)一样。但是,不是人就能写代码((programmer)&tom->coding() 可能无法调用,tom非programmer类)。那么,写代码这个行为(成员函数coding())就不属于人这个类了,而是子类的特性。但是人的基本行为,比如吃饭(eating())。就可以说,一个活生生的人正在吃饭((person)&jack ->eating() 调用成功),当然这个人实际上是一个程序员。
在内存结构上,子类独有的数据成员是在父类的数据成员所在的内存后面上增加一段
是这样的,在new Derived()时,是先调用父类的构造函数,然后调用子类的构造函数,一定是这样的过程。在析构时,是相反的顺序,即先调用子类的西沟函数,然后调用父类的析构函数。这里有一点特别需要注意,那就是通过这种方式Base b=new Derived();声明时,也就是用new创建一个子类对象,然后再把这个指针赋值给基类时,对于构造函数来说,仍然是先调用父类构造函数,然后是子类构造函数,但是析构函数只有把它们声明为虚析构函数时,才能先调用子类析构函数,然后是调用父类析构函数,如果不声明为虚析构函数,那么只能够调用父类的析构函数,这个就是用到new与析构函数时需要注意的地方。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)