自定义log4cxx滚动策略链接报错:未找到log4cxx::helpers::Object::cast符号
Object::cast in log4cxx 0.10.0 Multi-Inheritance Policy Alright, let's break down why you're hitting that linking error and how to fix it.
The Root Cause
Your SizeAndTimePolicy inherits from both TriggeringPolicy and RollingPolicy, and you're using LOG4CXX_CAST_ENTRY_CHAIN for both. Here's the problem:
- The
LOG4CXX_CAST_ENTRY_CHAINmacro generates acastmethod that chains up to the specified base class. When you use it twice, the second macro overrides the first generatedcastmethod. - Eventually, the chain tries to call
log4cxx::helpers::Object::cast—but this symbol doesn't exist in the log4cxx 0.10.0 library (as you confirmed withnm -D). The library only provides the template-basedObjectPtrT::castinstead.
The Fix: Manual cast Implementation
Instead of relying on the problematic macro, write the cast methods yourself to properly handle both base classes. Here's how:
- Update your header file
Remove the twoLOG4CXX_CAST_ENTRY_CHAINlines and add declarations for manualcastmethods, plus ensure your class's type info is correctly implemented:
#include <log4cxx/rolling/rollingpolicy.h> #include <log4cxx/rolling/triggeringpolicy.h> namespace log4cxx { namespace rolling { class SizeAndTimePolicy : public TriggeringPolicy, public RollingPolicy { public: // ... your existing constructor, destructor, and method declarations ... // Manual cast implementations const void* cast(const helpers::Class& clazz) const override; void* cast(const helpers::Class& clazz) override; // Type info methods (replace any macro-generated versions) static const helpers::Class& getStaticClass(); const helpers::Class& getClass() const override; }; }} // namespace log4cxx::rolling
- Implement the methods in your .cpp file
Write thecastlogic to check your class first, then both base classes, avoiding the missingObject::castcall:
#include "CustomLogPolicies.h" using namespace log4cxx::rolling; const void* SizeAndTimePolicy::cast(const helpers::Class& clazz) const { // Check if we're casting to our own class if (clazz.isAssignableFrom(getStaticClass())) { return this; } // Check TriggeringPolicy first const void* triggerCast = TriggeringPolicy::cast(clazz); if (triggerCast != nullptr) { return triggerCast; } // Then check RollingPolicy const void* rollingCast = RollingPolicy::cast(clazz); if (rollingCast != nullptr) { return rollingCast; } // No match found—return null instead of calling missing Object::cast return nullptr; } void* SizeAndTimePolicy::cast(const helpers::Class& clazz) { if (clazz.isAssignableFrom(getStaticClass())) { return this; } void* triggerCast = TriggeringPolicy::cast(clazz); if (triggerCast != nullptr) { return triggerCast; } void* rollingCast = RollingPolicy::cast(clazz); if (rollingCast != nullptr) { return rollingCast; } return nullptr; } // Implement type info (adjust the base class reference if needed) const helpers::Class& SizeAndTimePolicy::getStaticClass() { static const helpers::Class theClass("SizeAndTimePolicy", &TriggeringPolicy::getStaticClass()); return theClass; } const helpers::Class& SizeAndTimePolicy::getClass() const { return getStaticClass(); } // ... your existing implementation for delegating to TBRP and SBTP ...
Why This Works
By manually handling the cast chain, you avoid the macro's limitation of only supporting one base class. You explicitly check both TriggeringPolicy and RollingPolicy before returning null, skipping the call to the missing Object::cast method entirely.
Optional Alternative: Adjust Inheritance Design
If you'd prefer to avoid multi-inheritance headaches, you could refactor SizeAndTimePolicy to only inherit from RollingPolicy, then internally hold a SizeBasedTriggeringPolicy instance and delegate all TriggeringPolicy methods to it. This requires more boilerplate code but sidesteps the cast macro issue entirely.
内容的提问来源于stack exchange,提问作者metageek

