C++ 类继承(廿一)--基类、派生类、多态继承、公有继承、私有继承、虚函数、保护继承、多重继承

时间:2022-09-08 08:23:20


C++ 类继承(廿一)--基类、派生类、多态继承、公有继承、私有继承、虚函数、保护继承、多重继承


概念:创建派生类对象时,程序首先调用基类的构造函数,然后再调用派生类的构造函数。基类构造函数负责初始化继承的数据成员,派生类构造函数主要用于初始化新增的数据成员。派生类构造函数总是调用一个基类构造函数。可以使用初始化列表语法指明要使用的基类构造函数,否则使用默认的基类构造函数。


C++三种继承方式:公有继承、私有继承、保护继承


特殊关系:1、派生类可以调用基类的方法,前提不是私有函数;

           2、基类指针可以不进行显式类型转换下指向派生类对象;

3、基类引用可以不进行显式类型转换下引用派生类对象;

4、基类指针或用引用只能调用基类方法。

注意:不能将基类引用和地址赋值给派生类对象和地址


C++ 类继承(廿一)--基类、派生类、多态继承、公有继承、私有继承、虚函数、保护继承、多重继承


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.cpp

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 */


RatePlayer.cpp

//利用成员初始化列表语法,在派生类创建前对基类初始化
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.使用虚方法

注意: *构造函数不可以是虚函数

                 *析构函数应该设置为虚函数,这样当派生类过期时会先调用派生类的析构函数,否则将直接调用基类的析构函数释放派生类的基类中内存部分,而不释放派生类新成员内存

 *友元不能是析构函数,友元不是类成员,只有成员才能是虚函数,也可以通过友元函数使用虚成员函数来解决


C++ 类继承(廿一)--基类、派生类、多态继承、公有继承、私有继承、虚函数、保护继承、多重继承

C++ 类继承(廿一)--基类、派生类、多态继承、公有继承、私有继承、虚函数、保护继承、多重继承

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();


//保护继承

基类的公有成员函数在保护继承的派生类 变成了保护成员函数

C++ 类继承(廿一)--基类、派生类、多态继承、公有继承、私有继承、虚函数、保护继承、多重继承



//多重继承

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;