2008年8月6日星期三

C++中类的继承特性

RT

同样是学习笔记~同样所有的都在代码里~

修改日期:2008-8-6
--------------------------------------------------
// 子类和父类的构造/析构函数调用顺序

// 声明子类对象时
// 首先会调用父类的构造函数,然后调用子类的构造函数
// 销毁子类对象是,先调用子类的析构函数,然后调用父类的构造函数
// 即构造函数和析构函数的调用顺序相反

class Animal
{
 public:
  Animal();  // 父类构造函数
  ~Animal(); // 父类析构函数
  int ReadHead();
  void SetHead(int n); 

 protected:
  int m_nHead; // 子类能直接访问父类的public和protect成员
};

class Bear : public Animal
{
 public:
  Bear();  // 子类构造函数 
  ~Bear(); // 子类析构函数

 private:
  int m_nLegs;
};


#include <conio.h>
#include <iostream>
#include "SolveHead.h"
using namespace std;

int main()
{
 // 声明子类对象,会顺序输出
 // Animal Constructor
 // Bear Constructor
 Bear MyBear;

 cout<<endl<<"Press any key to exit!"<<endl;
 getch();

 // 销毁对象,会顺序输出
 // Bear Destructor
 // Animal Destructor
  return 0;
}

// --------------------------
// Bear Class - child class

Bear::Bear()
{
 cout<<"Bear Constructor"<<endl;
}

Bear::~Bear()
{
 cout<<"Bear Destructor"<<endl;
}

// -----------------------------
// Animal Class - Derived class

Animal::Animal()
{
 cout<<"Animal Constructor"<<endl;
}

Animal::~Animal()
{
 cout<<"Animal Destructor"<<endl;
}

int Animal::ReadHead()
{
 return m_nHead;
}

void Animal::SetHead(int n)
{
 m_nHead = n;
}

--------------------------------------------------
// 子类的拷贝构造函数

// 在通过子类的拷贝构造函数初始化对象时,应同时调用父类的构造函数
// 对该对象进行初始化
// 因为对于子类对象的复制过程,编译器不会自动调用父类的构造函数
// 如此一来会导致父类成员的丢失

class Animal
{
 public:
  Animal();
  Animal(Animal &temp);  // 父类的拷贝构造函数
  ~Animal();
  int ReadHead();
  void SetHead(int n); 

 protected:
  int m_nHead;
};

class Bear : public Animal
{
 public:
  Bear();
  Bear(Bear &temp);  // 子类的拷贝构造函数
  ~Bear();      // 在调用子类拷贝构造函数时,应同时调用父类构造函数
  int GetLegs();

 private:
  int m_nLegs;
};


#include <conio.h>
#include <iostream>
#include "SolveHead.h"
using namespace std;

int main()
{
 Bear MyBear;

 cout<<"MyBear's Head: "<<MyBear.ReadHead()<<endl;  // 输出1
 cout<<"MyBear's Legs: "<<MyBear.GetLegs()<<endl;  // 输出4

 Bear NewBear(MyBear);

 cout<<"NewBear's Head: "<<NewBear.ReadHead()<<endl;  // 如果下面没有调用: Animal(temp)
                            // 则输出的是一个随机值,否则是1
 cout<<"NewBear's Legs: "<<NewBear.GetLegs()<<endl;  // 输出4

 cout<<endl<<"Press any key to exit!"<<endl;
 getch();
  return 0;
}

// --------------------------
// Bear Class - child class

Bear::Bear()
{
 //初始化对象
 Bear::m_nHead = 1;
 Bear::m_nLegs = 4;
}

Bear::Bear(Bear &temp) : Animal(temp)  // 子类拷贝构造函数的体现
{                    // 如果不写: Animal(temp)
 Bear::m_nLegs = temp.m_nLegs;     // 则会导致无法初始化m_nHead
}

Bear::~Bear()
{
 
}

int Bear::GetLegs()
{
 return m_nLegs;
}

// -----------------------------
// Animal Class - Derived class

Animal::Animal()
{
 
}

Animal::Animal(Animal &temp) // 通过传递,初始化新对象的父类成员
{
 Animal::m_nHead = temp.m_nHead;
}

Animal::~Animal()
{

}

int Animal::ReadHead()
{
 return m_nHead;
}

void Animal::SetHead(int n)
{
 m_nHead = n;
}

--------------------------------------------------
// 继承中的组合问题

// 当一个类的成员是另一个类的对象的时候就叫做组合,事实上就是类于类的组合。
// 下面借用一个别人的例子

#include <iostream>  
using namespace std;  
  
class Vehicle  
{  
public:  
    Vehicle(float speed=0,int total=0)  
    {  
        Vehicle::speed = speed;  
        Vehicle::total = total;  
    }  
protected:  
    float speed;//速度  
    int total;//最大载人量  
};  
  
class Motor  
{  
public:  
    Motor(char *motor)  
    {  
        Motor::motortype = motor;  
    }  
  
    char* SMT(Motor &temp);  
protected:  
    char *motortype;//发动机型号  
};  
char* Motor::SMT(Motor &temp)  
{  
    return temp.motortype;  
}  
  
class Car:public Vehicle//继承的体现  
{  
public:  
    Car(float speed,int total,int aird,char *motortype):Vehicle(speed,total),motor(motortype)  
    {  
        Car::aird = aird;  
    }  
  
    Motor rm(Car &temp);  
protected:  
    int aird;//排量  
    Motor motor;//类组合的体现  
};  
  
Motor Car::rm(Car &temp)  
{  
    return temp.motor;  
}  
  
//--------------------------------------------------------------  
void test1(Vehicle &temp)  
{  
    //中间过程省略  
};  
void test2(Motor &temp)  
{  
    cout<<temp.SMT(temp);//读者这里注意一下,temp既是对象也是对象方法的形参  
}  
//--------------------------------------------------------------  
  
void main()  
{  
    Car a(150,4,250,"奥地利AVL V8");  
    test1(a);  
    //test2(a);//错误,Car类与Motor类无任何继承关系  
    test2(a.rm(a));//如果Car类成员是public的那么可以使用test2(a.motor)  
    cin.get();  
}

// 在上面的代码中我们新增加了发动机类Motor,Car类增加了Motor类型的motor成员,这就是组合
// 拥有继承特性的派生类可以操作基类的任何成员,但对于与派生类组合起来的普通类对象来说
// 它是不会和基类有任何联系的。 

// 函数调用:test1(a);,可以成功执行的原因就是因为Car类对象在系统是看来一个Vehicle类对象
// 即Car类是Vehicle类的一种,Car类的覆盖范围包含了Vehicle。

// 函数调用:test2(a);,执行错误的原因是因为Motor类并不认可Car类对象a与它有任何关系
// 但我们可以通过使用Car类对象a的Motor类成员motor,作为函数形参的方式来调用test2函数(test2(a.motor))
// 在这里由于类的成员是受保护的所以我们利用a.rm(a)来返回受保护的motor,作为函数参数进行调用。

没有评论:

发表评论

1、可以使用<b>、<i>、<a>等Html标志,让评论更有特色...
2、支持OpenID登录,技术达到国际先进水平。但切记,评论内容不代表本站观点!
3、当遇到“连接被重置”、“连接超时”和“此网页无法访问”等而发表不了评论的话,请多刷新几次页面,或迟三分钟后再试;
4、对你的浏览造成不便,站长在此代表全国G.FW工作人员向你鞠躬致歉!!!