使用-fno-rtti编译的共享库中的子类
Subclassing class from shared library compiled with -fno-rtti
我正在尝试从使用-fno rtti编译的共享库中派生子类。不幸的是,我的代码库中的其他库需要-frtti。结果我得到了链接错误,因为超类没有typeinfo结构。
在正常编译中收到错误:
out.o: in function typeinfo for MyClass:myclass.cpp(.data.rel.ro.<cpp magic>): error: undefined reference to 'typeinfo for NetlinkListener'
我想要子类化的类是libsysutils中的一个android类(为节省空间而略作删减(:
class NetlinkListener : public SocketListener {
char mBuffer[64 * 1024];
int mFormat;
public:
static const int NETLINK_FORMAT_ASCII = 0;
static const int NETLINK_FORMAT_BINARY = 1;
NetlinkListener(int socket);
NetlinkListener(int socket, int format);
virtual ~NetlinkListener() {}
protected:
virtual bool onDataAvailable(SocketClient *cli);
virtual void onEvent(NetlinkEvent *evt) = 0;
};
我的存根看起来像:
class MyClass: public NetlinkListener {
public:
MyClass();
virtual ~MyClass();
int start();
int stop();
protected:
virtual void onEvent(NetlinkEvent *evt);
};
MyClass中的所有方法都实现了(作为空存根(
我无法编译共享库-frtti。有什么办法解决这个问题吗?
1(对于简单的情况,您可以只创建接口的C包装器(不使用RTTI构建(。然后,您可以在支持RTTI的程序中使用C接口,前提是您将它们视为支持RTTI程序中的抽象C类型。
2( 使用RTTI编译库正是应该做的(或供应商的要求(,除非有充分的理由禁用RTTI(例如,您在不应该使用异常的域中工作,例如内核、驱动程序或其他无异常区域,或者内存紧张(。
3( 将库更改为不使用dynamic_cast、exceptions、typeid运算符或任何导致问题的运算符,并在禁用RTTI的情况下重新生成。与1类似,您可以将其作为一个单独的抽象库,这取决于程序的组织方式。
4a(下一个选项是永远不要引用对象的类型信息(例如,不要dynamic_cast或抛出它(——这可能会很痛苦。这将删除引用类型infos的链接器错误。
4b(创建内部类可能是最简单的(假设有一些方法必须重写,并且有一些类型必须与依赖rtti的程序接口(。您可以创建一个类型(inner
(,该类型继承自其lib的类型并执行必要的重写,但随后通过某些其他类层次结构进行回调(其他层次结构可以自由使用rtti(。现在,inner
类的虚拟导出被放置在禁用rtti的TU中(因为它将隐式引用其基类的类型信息(。然后,您可以很容易地隔离类型信息依赖性,并构建一个使用异常之类的东西的层次结构——该层次结构使用inner
类型作为值。当然,如果有效,那么这都是实现定义的——您需要了解RTTI和vtables是如何为您的目标平台构建的(请参阅ABI参考文献(。即使省略RTTI也是对标准C++的偏离。没有任何信息表明,符号的存在将导致vtables的正确构建,以及在没有这些功能的情况下编译的基的类型信息。
也就是说,1和2是你的安全选项,3在无rtti平台扩展(安全(的范围内,4是一种可以在无系统或仅在某些系统上自由工作的方法。
说明4b
class MyClass // << cast me. throw/catch me. get my mangled name,
// but put my family's virtual exports in a TU with RTTI enabled
: public MyRTTIEnabledFamily {
public:
MyClass() : d_inner(*this) {}
virtual ~MyClass();
private:
void cb_onEvent(NetlinkEvent * evt) {
// no-rtti suggests exceptions may not be available,
// so you should be careful if your program throws.
someInfo = evt->getInfo();
}
private:
// non-rtti hierarchy
class t_inner : public NetlinkListener {
public:
t_inner(MyClass& pMyClass) : NetlinkListener(), d_myClass(pMyClass) {
}
virtual ~t_inner(); // << put your virtual exports in a TU with RTTI disabled.
// one out of line virtual definition is necessary for most compilers
private:
virtual void onEvent(NetlinkEvent * evt) {
// how the callback to your imp actually happens
this->d_myClass.cb_onEvent(evt);
}
private:
MyClass& d_myClass;
};
private:
t_inner d_inner; // << don't do anything with my type info -- it does not exist.
};
根据gcc的文档,传递-fno-rtti
仅禁用dynamic_cast
和typeid
功能。您应该能够在没有任何问题的情况下派生类和使用虚拟方法。
如果您将函数声明为virtual
而没有为其提供定义,则通常会出现undefined reference to typeinfo for class
错误
事实上,我看到AOSP中的NetlinkHandler.h
和NetlinkHandler.cpp
正是在做你想要做的事情,我没有发现这些文件和你发布的代码片段之间有任何区别。
- 继承期间显示未知行为的子类
- 通过指向指针数组的指针访问子类的属性
- 从父类方法返回子类对象
- c++, 在子类中,如何在没有对象的情况下访问父类的方法?
- 将父类对象强制转换为子类的问题
- 避免在C++中重复子类定义
- 将QOpenGLWidget子类转换为使用Metal而不是OpenGL的子类是否可行?
- 如何初始化矢量的模板化子类
- C++ 继承:将子类传递给需要基类的函数并获取子类行为
- C++子类共享变量?
- 跨子类的共享指针
- 共享库中非模板基的模板子类导致未定义的符号类型信息'class'链接错误
- 多个小型函子类的共享头文件
- 如何让一组不同的子类对象从另一组共享基类的一个静态变量
- 子类是否共享C++父类的静态变量
- c++虚方法:必须在父类中为父类和子类不共享的每个方法创建一个虚方法吗?
- 从共享库加载方法,该方法调用在子类中实现的方法
- 使用-fno-rtti编译的共享库中的子类
- Polymoprhism - 基类私有成员的子类共享
- 共享父类成员的子类