C++ 继承特性

——派生类须要本身的构造函数。函数

    派生类中能够根据须要添加额外的数据成员和成员函数,甚至能够给予继承的原成员函数新的定义。this

  基类指针或引用可指向派生对象,反过来则只能使用强制类型转换。spa

  派生类对象可以使用基类的非私有成员。指针

  可以使用派生对象初始化基类对象或赋值。code

  通常不容许将基类对象赋给派生类对象(上面第三条),特殊状况下能够。对象

  已有派生类对象初始化建立的派生类对象。blog

  已有派生类对象给另外一个派生类对象赋值。继承

  派生类对象的析构函数被调用后会自动调用基类的析构函数。内存

  C++11增长了容许继承构造函数的机制,但派生类默认不能继承构造函数和析构函数。ci

 

class RatedPlayer : public TableTennisPlayer
 {
 private:
     unsigned int rating;    // add a data member
 public:
     RatedPlayer (unsigned int r = 0, const string &fn = "none", const string &ln = "none", bool ht = false);
     RatedPlayer (unsigned int r, const TableTennisPlayer &tp);
     unsigned int Rating() const { return rating; }    // add a method
     void ResetRating (unsigned int r) { rating = r; }    // add a method
};

   构造函数必须给新成员和继承的成员提供数据。

RatedPlayer::RatedPlayer(unsigned int r, const string &fn, const string &ln, bool ht) : TableTennisPlayer(fn, ln, ht)
{
    rating = r;
}
  • 派生类构造函数必须使用基类构造函数,建立派生类对象时,程序首先建立基类对象(初始化继承的数据成员)而后再调用派生类构造函数。C++使用成员初始化列表语法完成该操做。
  • 如没有调用基类构造函数,那么将隐式调用基类的默认构造函数。除非要使用默认构造函数,不然应显示调用正确的基类构造函数。

  派生类对象过时时,程序将首先调用派生类析构函数,而后再自动调用基类析构函数。

  要使用派生类,程序必需要能访问基类声明。

  派生类对象可使用基类的方法,条件是方法不是私有的(即公有和保护)。

 

  基类指针能够在不进行显示类型转换的状况下指向派生类对象;基类引用能够在不进行显示类型转换的状况下引用派生类对象

RatedPlayer rplayer(1140, "Mallory", "Duck", true);
TableTennisPlayer &rt = rplayer;
TableTennisPlayer *pt =&rplayer;
rt.Name();    // invoke Name() with reference
pt->Name();    // invoke Name() with pointer

  不能够将基类对象和地址赋给派生类引用和指针,除非使用强制转换(友元函数不是成员函数所以不能被继承,但欲使用基类的友元函数时可以使用此方法,但要当心用错)。

  基类声明的函数引用参数或指针参数可用于值为基类对象或派生类对象以及它们的地址的状况。

void Show(const TableTennisPlayer &rt)
{
    ...
}

 

 

TableTennisPlayer player1("Tara", "Boomdea", false);
RatedPlayer rplayer1(1140, "Mallory", "Duck", true);
Show(player1);    // works with TableTennisPlayer argument
Show(rplayer1);    // works with RatedPlayer argument

  省略形参为const TableTennisPlayer *rt的状况,与上类似。

  引用兼容性属性:能够将基类对象初始化为派生类对象。

RatedPlayer olaf1(1840, "Olaf", "Loaf", true);
TableTennisPlayer olaf2(olaf1);

   匹配的构造函数的原型:

TableTennisPlayer(const RatedPlayer &);    // doesn't exit

 

  类中并无该构造函数,但存在隐式复制构造函数:

// implicit copy constructor
TableTennisPlayer(const TableTennisPlayer &);

   即它将olaf2初始化为嵌套在RatedPlayer对象olaf1中的TableTennisPlayer对象(使用派生类中嵌套的基类对象对目标基类对象进行初始化)

  一样,也能够将派生对象赋给基类对象:

RatedPlayer olaf1(1840, "Olaf", "Loaf", true);
TableTennisPlayer winner;
winner = olaf1;    // assign derived to base object

   在这种状况下,程序使用隐式重载赋值运算符:

TableTennisPlayer &operator=(const TableTennisPlayer &) const;

   与上相似,使用派生类中嵌套的基类对象对目标基类对象进行按成员赋值。

 

  特殊的用基类对象给派生类对象赋值的状况

  若是派生类包含了将基类对象转换为派生类对象的构造函数,或派生类定义了将基类对象赋给派生类对象的赋值运算符,则能够用派生类对象给基类对象赋值。

 

  用已有的派生类对象初始化建立的派生类对象

  复制类成员或继承的类组件时,则是使用该类的复制构造函数完成的,对于继承的基类对象来讲也是合适的。

  用已有的派生类对象给另外一个派生类对象赋值

  按成员赋值,调用类成员赋值运算符,使用基类的赋值运算符来对基类组件(继承的基类对象)进行赋值

 

  若派生类使用了动态内存分配,派生类的析构函数、复制构造函数、复制运算符都必须使用相应的基类方法来处理基类元素(显示调用基类构造函数和复制运算符): 

  • 对于析构函数,这是自动完成的。
  • 对于复制构造函数,这是在初始化成员列表中调用基类的复制构造函数来完成的;若是不这么作,将自动调用基类的默认构造函数。
  • 对于复制运算符,这是经过使用做用域解析运算符显示地调用基类的赋值运算符来完成的:

 

hasDMA &hasDMA::operator=(const hasDMA &has)
{
    if (this == &hs)
        return *this;
    baseDMA::operator=(hs);    // copy base portion
    ...
    return *this;    
}

  

  ---

相关文章
相关标签/搜索