6.26 using声明与继承

using声明有时候被用于调整对基类成员的访问。例如:

class Foo {
public:
    int blah(int x);
};

class Bar {
public:
    double blah(double x);
};

class FooBar : public Foo, public Bar {
public:
  using Foo::blah;
  using Bar::blah;

  char *blah(const char *x);
};

在这个例子中,using声明在派生类中引入了不同版本重载的blah()方法。例如:

FooBar *f;
f->blah(3); // Ok. Invokes Foo::blah(int)
f->blah(3.5); // Ok. Invokes Bar::blah(double)
f->blah("hello"); // Ok. Invokes FooBar::blah(const char *);

当这样的代码被包装时,SWIG也会模拟类似的功能。例如,如果你在Python中包装这段代码时,工作方式和你期望的方式一样:

>>> import example
>>> f = example.FooBar()
>>> f.blah(3)
>>> f.blah(3.5)
>>> f.blah("hello")

using声明还能用于改变访问方式。例如:

class Foo {
protected:
  int x;
  int blah(int x);
};

class Bar : public Foo {
public:
  using Foo::x;     // Make x public
  using Foo::blah;  // Make blah public
};

SWIG也支持这样的工作方式——包装后也能正常工作。

using声明通过上面的方式使用时,基类中的声明被拷贝至派生类,然后正常包装。当拷贝时,这些声明依然保持使用%rename%ignore%feature指令关联的任何属性。因此,如果方法在基类中被忽略,即使使用了using声明也还是被忽略。

由于using声明不提供对导入声明的细粒度控制,对这些声明的管理可能很困难,要使用很多SWIG自定义特性。如果你不能让using正确的工作,你总能像下面这样做:

class FooBar : public Foo, public Bar {
public:
#ifndef SWIG
using Foo::blah;
using Bar::blah;
#else
int blah(int x); // explicitly tell SWIG about other declarations
double blah(double x);
#endif
char *blah(const char *x);
};

注意:

  • 如果派生类重新定义了基类的方法,using声明也不会导致冲突。例如:
class Foo {
public:
  int blah(int );
  double blah(double);
};

class Bar : public Foo {
public:
    using Foo::blah; // Only imports blah(double);
    int blah(int);
};
  • 消除重载的歧义可以通过使用using导入声明来实现。例如:
%rename(blah_long) Foo::blah(long);
class Foo {
public:
  int blah(int);
  long blah(long); // Renamed to blah_long
};

class Bar : public Foo {
public:
  using Foo::blah; // Only imports blah(int)
  double blah(double x);
};

results matching ""

    No results matching ""