概念:创建派生类对象时,程序首先调用基类的构造函数,然后再调用派生类的构造函数。基类构造函数负责初始化继承的数据成员,派生类构造函数主要用于初始化新增的数据成员。派生类构造函数总是调用一个基类构造函数。可以使用初始化列表语法指明要使用的基类构造函数,否则使用默认的基类构造函数。
C++三种继承方式:公有继承、私有继承、保护继承
特殊关系:1、派生类可以调用基类的方法,前提不是私有函数;
2、基类指针可以不进行显式类型转换下指向派生类对象;
3、基类引用可以不进行显式类型转换下引用派生类对象;
4、基类指针或用引用只能调用基类方法。
注意:不能将基类引用和地址赋值给派生类对象和地址
TablePlayer.hpp
#ifndef TablePlayer_hpp
#define TablePlayer_hpp
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
class TablePlayer {
private:
string firstName;
string lastName;
bool hasTable;
public:
//成员初始化列表语法(如果调用时不传实参,则使用默认值),构造函数,用引用&可以减少创建新变量占用内存及提高速度
TablePlayer(const string &fn = "dadf", const string &ln = "nono",bool bl = false);
//如果析构函数不作任何处理,可以忽略不写
~TablePlayer(){}
void Name();
bool HasTable(){return hasTable;};
void ResetTable(bool b){ hasTable = b;};
};
//派生类RatePlayer写在一齐方便,也可以写在另一个文件 公有基类 TablePlayer
class RatePlayer : public TablePlayer{
};
#endif /* TablePlayer_hpp */
TablePlayer::TablePlayer(const string &fn, const string &ln,bool bl):firstName(fn) ,lastName(ln), hasTable(bl)
{
}
void TablePlayer::Name()
{
cout << lastName << "," << firstName << endl;
}
RatePlayer.hpp
#ifndef RatePlayer_hpp
#define RatePlayer_hpp
#include <stdio.h>
#include <iostream>
#include <string>
#include "TablePlayer.hpp"
//派生类RatePlayer 公有基类 TablePlayer
class RatePlayer2 : public TablePlayer {
private:
unsigned int rating;
public:
//派生类需要有自己的构造函数
RatePlayer2(unsigned int i = 0 , const string & fn = "fn" ,const string & ln = "ln",bool b = false);
RatePlayer2(unsigned int i , const TablePlayer &t);
unsigned int Rating(){return rating;};
void ResetRateing(unsigned int i){rating = i;};
};
#endif /* RatePlayer_hpp */
//利用成员初始化列表语法,在派生类创建前对基类初始化
RatePlayer2::RatePlayer2(unsigned int i , const string & fn ,const string & ln ,bool b):TablePlayer(fn,ln,b)
{
rating = i;
}
RatePlayer2::RatePlayer2(unsigned int i , const TablePlayer &t):TablePlayer(t),rating(i)
{
}
main
#include <iostream>
#include "TablePlayer.hpp"
#include "RatePlayer.hpp"
int main(int argc, const char * argv[]) {
//基类
TablePlayer t1("1","111",true);
TablePlayer t2;
t1.Name();
if (t1.HasTable())
{
cout << "has table\n";
}
else
{
cout << "has not table\n";
}
t2.Name();
if (t2.HasTable())
{
cout << "has table\n";
}
else
{
cout << "has not talbe\n";
}
//派生类,直接调用基类方法
RatePlayer2 r;
r.Name();
r.ResetTable(false);
//基类指针指向派生类对象
TablePlayer *t3 = &r;
//基类引用派生类对象
TablePlayer &t4 = r;
//派生类直接赋值给基类,
TablePlayer t5(r);
RatePlayer2 r2(100,"r2","rr",true);
t5 = r2;
return 0;
}
//多态继承 虚函数
1.在派生类中重新定义基类的方法
2.使用虚方法
注意: *构造函数不可以是虚函数
*析构函数应该设置为虚函数,这样当派生类过期时会先调用派生类的析构函数,否则将直接调用基类的析构函数释放派生类的基类中内存部分,而不释放派生类新成员内存
*友元不能是析构函数,友元不是类成员,只有成员才能是虚函数,也可以通过友元函数使用虚成员函数来解决
class Bass {
private:
int i;
double f;
public:
Bass(const int bi = 10, const double bf = 33.34f):i(bi),f(bf){};
virtual void Check(){ cout << "Base::Check" << endl; };
virtual ~Bass(){};
};
class BassSub:public Bass {
private:
int t;
double k;
public:
BassSub(const int bi = 10, const double bf = 33.34f):t(bi),k(bf){};
virtual void Check(){ cout << "BaseSub::Check" << endl; };
virtual ~BassSub(){};
};
//虚函数 Bass b(10,333.34f); BassSub sb(2223,112.5f); b.Check(); //Base::Check sb.Check(); //BaseSub::Check
//私有继承
私有继承的派生类只能在内部调用基类的公有函数,私有继承初始化后外部不能调用基类公有函数
class Test {
private:
string name;
valarray<double> source;
public:
void come()
{
cout << "private" << endl;
}
protected:
};
class tt : private Test {
public:
void doCome()
{
this->come();
}
};
main
//私有继承
tt t;
t.doCome();
//保护继承
基类的公有成员函数在保护继承的派生类 变成了保护成员函数
//多重继承
class BaseFirst {
int bb;
public:
int bf;
};
class BaseSec {
public:
int bs;
};
class Derived : public BaseFirst , public BaseSec {
public:
int d;
};
//多重继承
Derived derived;
derived.bf = 10;
derived.bs = 20;
derived.d = derived.bf+derived.bs;