前言:有时候会混合使用抽象类与接口,分不清什么时候使用抽象类,什么时候使用接口。
一般来说,抽象类为继承体系表示继承关系,接口为层次体系表示能力。
实现:炊事员与陆军都属于部队,但陆军会开枪,猎人也会。所以将陆军与炊事员抽象出士兵类,开枪的能力抽象出接口。
CPP:
士兵类:
enum RANK
{
OR_1,
OR_2,
};
class SolidersBase
{
public:
SolidersBase(RANK rank) :rank(rank) {}
virtual RANK GetRank() = 0;
protected:
RANK rank;
};
开枪接口:
class IShooting
{
public:
virtual void Shooting() = 0;
};
派生类实现:
class Army :public SolidersBase, public IShooting
{
public:
Army(RANK r) :SolidersBase(r) {}
RANK GetRank() override { return rank; }
void Shooting() override { std::cout << "Solider shoot" << std::endl; }
};
class Cook :public SolidersBase
{
public:
Cook(RANK r) :SolidersBase(r) {}
RANK GetRank() override { return rank; }
};
class Hunter :public IShooting
{
public:
void Shooting() override {
std::cout << "Hunter shoot" << std::endl;
}
};
调用:
SolidersBase* solider1 = new Cook(RANK::OR_1);
SolidersBase* solider2 = new Army(RANK::OR_2);
Hunter hunter;
std::cout << "solider1:" << solider1->GetRank() << "; " << "solider2:" << solider2->GetRank() << std::endl;
SomeOneShoot(&hunter);
SomeOneShoot((IShooting*)(Army*)(solider2));
if (auto* ifun = dynamic_cast<IShooting*>(solider1))
SomeOneShoot(ifun);
else
{
std::cout << "don't know shooting" << std::endl;
}
if (auto* ifun = dynamic_cast<IShooting*>(solider2))
SomeOneShoot(ifun);
else
{
std::cout << "don't know shooting" << std::endl;
}
注意:
调用时需要先转到继承了接口的类,再转接口。不然会出现虚函数调用错误问题(调用的不是想要调用的虚函数)。
或者使用dynamic_cast进行转换。
C#:C#有接口不会出现CPP虚表偏移的情况:
实现:
/// <summary>
/// 等级
/// </summary>
enum RANK
{
OR_1,
OR_2,
};
abstract class SolidersBase
{
protected RANK rank;
public SolidersBase(RANK rank)
{
this.rank = rank;
}
public abstract RANK GetRank();
}
/// <summary>
/// 炊事员
/// </summary>
class Cook : SolidersBase
{
public Cook(RANK rank)
: base(rank) { }
public override RANK GetRank()
{
return rank;
}
}
/// <summary>
/// 陆军
/// </summary>
class Army : SolidersBase, IShooting
{
public Army(RANK rank)
: base(rank) { }
public override RANK GetRank()
{
return rank;
}
public void Shooting()
{
Console.WriteLine("Solider shoot");
}
}
/// <summary>
/// 开枪
/// </summary>
interface IShooting
{
public void Shooting();
}
class Hunter : IShooting
{
public void Shooting()
{
Console.WriteLine("Hunter shoot");
}
}
static class ShootHelper
{
public static void SomeOneShoot(IShooting shooter)
{
shooter.Shooting();
}
}
调用:
SolidersBase solider1 = new Cook(RANK.OR_1);
SolidersBase solider2 = new Army(RANK.OR_2);
Hunter hunter = new();
ShootHelper.SomeOneShoot(hunter);
ShootHelper.SomeOneShoot((IShooting)solider2);
if (solider1 is IShooting shooter1)
ShootHelper.SomeOneShoot(shooter1);
else
{
Console.WriteLine("don't know shooting");
}
if (solider2 is IShooting shooter2)
ShootHelper.SomeOneShoot(shooter2);
else
{
Console.WriteLine("don't know shooting");
}