如果没有继承,类只是具有一些相关行为的数据结构,这只是对过程语言的一大改进,而继承则开辟了完全不同的新天地。通过继承,可以在已有类的基础上创建新类。这样,类就成为可重用和可扩展的组件。博主的《漫谈继承技术》系列博文将讲述各种利用继承功能的方法。学习继承的语法,和利用继承的一些复制技术。本篇博文先给大家介绍一下using在继承中的使用,希望对大家加深对继承技术的理解有一定的帮助。
using
可能大家用的最多的using命令是“usingnamespacestd;”,其实它在继承中也大有用武之地。下面我们来看个栗子吧。
#include <iostream>
#include <string>
using namespacestd;
//基类super1
class super1
{
public:
super1(){}
virtual~super1(){}
virtualvoidshow(const std::string&str) const;
};
void super1::show(conststd::string &str)const
{
cout<< __FUNCTION__ << ": "<< str << endl;
}
//基类super2
class super2
{
public:
super2(){}
virtual~super2(){}
virtualvoidshow(int nValue) const;
};
void super2::show(intnValue)const
{
cout<< __FUNCTION__ << ": "<< nValue << endl;
}
class subfinal: public super1,publicsuper2
{
public:
//usingsuper1::show;
sub(){}
virtual~sub(){}
virtualvoidshow(int nValue) constoverride;
};
void sub::show(intnValue)const
{
cout<< __FUNCTION__ << ": "<< nValue << endl;
}
int main()
{
//用基类指针指向派生类对象
sub *sp = new sub();
sp->show(12);
//sp->show("string");
//释放资源
deletesp;
//将基类指针置为nullptr,避免野指针
sp = nullptr;
return0;
}
程序运行结果:
如果我们在“sp->show(12);”下面再加上一条语句“sp->show("string");”会怎么样呢?编译器会报以下错误:
这是因为我们不仅在派生类中重写了基类的show方法,而且还将基类中的首位隐藏了。我们无法通过派生类对象、指针或引用去调用去调用被派生类隐藏的基类方法。其实编译器这样做的想法是:如果重写了给定名称的某个方法,可能是想重写所有的同名方法,只是忘记这么做了,因此应该作为错误处理。这个时候我们就可以借助using命令来解决这个问题,我们只需要在派生类的public字段内加上“usingsuper1::show;”,编译器就不会报以上错误了。
程序运行结果:
为了避免以上歧义bug,应该重写重载方法的所有版本,可以显示重写,也可以使用using关键字,但要留意using关键字的风险:假定我们在super1中添加了一个新的show方法,本来希望在sub类中重写这个方法。但是由于使用了using命令,在派生类中没有重写这个方法不会当做错误,sub类显示的说明“我将接收基类其他所有的重载方法”。
在C++中,隐藏未实现的方法(这里就是super1类的show方法)只是表象。显式声明为子类类型的实例对象无法使用这些方法,但可以将其转换为基类类型、基类指针或基类引用,以使用这些方法。如果不使用using命令,使用以下方式也可以调用super1类的show方法。
submysub;
super1 *ptr = &mysub;//指向派生类对象的基类指针
ptr->show("string");//OK
super1 &ref = mysub;//引用派生类对象的基类引用
ref.show("string");//OK
super1 mysuper = mysub;//将派生类对象向上转型为基类对象
mysuper.show("string");//OK
如果想了解更多关于继承技术相关的知识,请关注博主《漫谈继承技术》系列博文,相信你能够在那里寻找到更多有助你快速成长和深入你对继承相关的知识和一些复制的技术理解和掌握。