如果我们想在子类中继承那些重载函数,并重写其中的一部分(像本例中的mf1和mf3),那么可以使用using语句
让Base class内名为mf1和mf3的所有东西(所有重载函数)在Derived作用域内都是可见的。
class Base {
private:
int x;
public:
Base() {};
virtual void mf1() = 0;
virtual void mf1( int m ) { std::cout << "Base mf1 int: "<< m << std::endl; } ;
virtual void mf2() { std::cout << "Base mf2 " << std::endl; };
void mf3() { std::cout << "Base mf3" << std::endl;};
void mf3( double m ) { std::cout << "Base mf3 double:" << m << std::endl; };
};
class Derived : public Base {
public:
using Base::mf1; // 让Base class内名为mf1和mf3的所有东西(所有重载函数)
using Base::mf3; // 在Derived作用域内都是可见的。
virtual void mf1() { std::cout << "Derived mf1" << std::endl; };
void mf3() { std::cout << "Derived mf3" << std::endl; };
void mf4() { std::cout << "Derived mf4" << std::endl; };
};
调用:
Derived* d = new Derived();
d->mf1();
d->mf1(1);
d->mf2();
d->mf3();
d->mf3(1);
d->mf4();
运行截图:

上面这种技术告诉我们如何继承所有重载函数,实现is-a的关系。
有时候我们并不想继承base classes的所有函数,而是用public继承和名字遮掩规则又不符合public继承所包含的is-a关系。
因此,这里介绍一种转交函数技术,很简单,看一个例子就懂了。
class Base {
public:
virtual void mf1() = 0;
virtual void mf1(int );
....
};
class Derived : private Base {
public:
virtual void mf1() { Base::mf1(); } // 转交函数
......
};
小结:
derived classes内的名称会遮掩base classes内的所有相同名称的重载函数,在public继承下这个机制并不希望发挥作用。
可使用using声明式或转交函数来调用被遮掩的重载函数。
3 区分接口继承和实现继承
选择继承的集中情况:
a:希望derived classes只继承成员函数的接口
b:希望derived classes同时继承函数的接口和实现,又希望能够重写它们所继承的实现
c:希望derived classes同时继承函数的藉口和实现,并且不允许重写任何东西
看一个几何图形例子:
class Shape {
public:
virtual void draw() const = 0;
virtual void error(const std::string& msg);
int objectID() const;
};
class Rectangle: public Shape { ...... };
class Ellipse: public Shape { ...... };
首先考虑纯虚函数draw
pure virtual函数有两个最突出的特征:
它们必须被任何“继承了它们”的子类重新声明
它们在抽象class中通常没有定义
综合上面两个特征:声明一个纯虚函数的目的是为了让derived class只继承函数接口
满足了本节开头的情景a。
考虑虚函数error。
虚函数的目的是让derived classes继承该函数的接口和缺省实现。满足了情景b。
最后,考虑non-virtual函数objectID。
声明non-virtual函数的目的是为了令derived classes继承函数的接口及一份强制性实现。
对应了情景c。
纯虚函数、虚函数和非虚函数使得你可以精确地指定你想要derived classes继承的东西。
小结:
接口继承和实现继承不同。在public继承之下,derived classes总是继承base class的接口
pure virtual函数只具体指定接口继承。
virtual 函数具体指定接口继承及缺省实现继承。
non-virtual函数具体指定接口继承以及强制性实现继承。