You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++98下自定义dynamic_smart_pointer_cast链接错误及代码优化咨询

Hey there, let's work through your SmartPointer issues step by step—starting with that linker error that's blocking you, then fixing some logical bugs, and finally optimizing the implementation for C++98.

1. Fixing the Linker Error

The undefined reference error comes from two critical mismatches between your dynamic_smart_pointer_cast template definition and its friend declaration:

  • Parameter type mismatch: Your friend declaration expects a const SmartPointer<U>&, but your definition uses const SmartPointer<U*>& (extra * on U). This means the compiler can't match your call dynamic_smart_pointer_cast<BaseClass>(DerivedClassInstance) to any existing template.
  • Template parameter alignment: The friend declaration uses <class Y, class U>, while your definition uses <class T, class U>. While parameter names don't need to be identical, the signature must align to avoid compiler confusion.
  • Typo: You called sp.reference->addRef() (lowercase a) but the RC method is named AddRef() (uppercase A). This would cause a compiler error once the linker issue is resolved.

Fix these by updating the cast function definition to match the friend declaration exactly:

template <class Y, class U>
SmartPointer<Y> dynamic_smart_pointer_cast(const SmartPointer<U>& sp) {
    // ... corrected logic here
}

2. Fixing Logical Bugs in dynamic_smart_pointer_cast

Your original cast function had broken reference count handling:

  • You tried to delete new_sp.pData when new_sp was default-constructed (which sets pData to 0—harmless but unnecessary).
  • You didn't properly clean up the default RC instance created by new_sp before adopting the source's reference count.

Here's the corrected version:

template <class Y, class U>
SmartPointer<Y> dynamic_smart_pointer_cast(const SmartPointer<U>& sp) {
    SmartPointer<Y> new_sp;
    Y* casted_ptr = dynamic_cast<Y*>(sp.pData);

    if (casted_ptr != 0) {
        // Clean up the default reference count new_sp created
        if (new_sp.reference->Release() == 0) {
            delete new_sp.reference;
        }
        // Adopt the source's pointer and increment its reference count
        new_sp.pData = casted_ptr;
        new_sp.reference = sp.reference;
        new_sp.reference->AddRef();
    }

    return new_sp;
}

If the dynamic_cast fails, new_sp stays in its default empty state (null pData and a reference count of 0).

3. Critical Fixes & Optimizations for SmartPointer

Your implementation has a few hidden bugs and areas for improvement:

a. Uninitialized Reference Count

Your RC class doesn't initialize the count member variable! This means the reference count starts with a random garbage value, which will completely break the pointer's lifecycle. Fix this by adding a constructor to RC:

class RC {
private:
    int count; // Reference count
public:
    RC() : count(0) {} // Initialize count to 0
    void AddRef() {
        __sync_add_and_fetch(&count, 1);
    }
    int Release() {
        return __sync_sub_and_fetch(&count, 1);
    }
};

b. Incorrect operator!() Logic

Your operator!() returns true when the reference exists, but it should return true when the pointer is empty. Update it to:

bool operator!() const {
    return (pData == 0);
}

c. Const-Correct Dereference Operators

Add const versions of operator* and operator-> so you can use const SmartPointer instances:

const T& operator*() const {
    return *pData;
}
const T* operator->() const {
    return pData;
}

d. Broken Raw Pointer Comparison

Your operator== and operator!= for void* compare the reference pointer instead of the actual pData. Fix this to match expected behavior:

bool operator==(const void* other) const {
    return (pData == static_cast<const T*>(other));
}
bool operator!=(const void* other) const {
    return !(*this == other);
}

4. Full Optimized C++98-Compatible Implementation

Here's the complete, fixed header with all the above changes:

#ifndef __SMART_POINTER_HEADER__
#define __SMART_POINTER_HEADER__

class RC {
private:
    int count; // Reference count
public:
    RC() : count(0) {} // Initialize reference count to 0
    void AddRef() {
        // Thread-safe increment (GCC extension, common in C++98 environments)
        __sync_add_and_fetch(&count, 1);
    }
    int Release() {
        // Thread-safe decrement
        return __sync_sub_and_fetch(&count, 1);
    }
};

template <typename T>
class SmartPointer {
private:
    T* pData; // Raw pointer to the object
    RC* reference; // Reference count tracker

public:
    // Default constructor: empty smart pointer
    SmartPointer() : pData(0), reference(0) {
        reference = new RC();
        reference->AddRef();
    }

    // Constructor from raw pointer (explicit to prevent implicit conversions)
    explicit SmartPointer(T* pValue) : pData(pValue), reference(0) {
        reference = new RC();
        reference->AddRef();
    }

    // Copy constructor
    SmartPointer(const SmartPointer<T>& sp) : pData(sp.pData), reference(sp.reference) {
        reference->AddRef();
    }

    // Destructor
    ~SmartPointer() {
        if (reference) {
            if (reference->Release() == 0) {
                delete pData;
                delete reference;
            }
            reference = 0;
            pData = 0;
        }
    }

    // Dereference operators (non-const)
    T& operator*() {
        return *pData;
    }

    T* operator->() {
        return pData;
    }

    // Dereference operators (const)
    const T& operator*() const {
        return *pData;
    }

    const T* operator->() const {
        return pData;
    }

    // Assignment operator
    SmartPointer<T>& operator=(const SmartPointer<T>& sp) {
        if (this != &sp) { // Avoid self-assignment
            // Clean up current resources
            if (reference) {
                if (reference->Release() == 0) {
                    delete pData;
                    delete reference;
                }
            }
            // Adopt the source's resources
            pData = sp.pData;
            reference = sp.reference;
            reference->AddRef();
        }
        return *this;
    }

    // Boolean negation: returns true if pointer is empty
    bool operator!() const {
        return (pData == 0);
    }

    // Equality comparison with another SmartPointer
    bool operator==(const SmartPointer<T>& other) const {
        return (reference == other.reference);
    }

    // Equality comparison with raw pointer
    bool operator==(const void* other) const {
        return (pData == static_cast<const T*>(other));
    }

    // Inequality comparison with another SmartPointer
    bool operator!=(const SmartPointer<T>& other) const {
        return !(*this == other);
    }

    // Inequality comparison with raw pointer
    bool operator!=(const void* other) const {
        return !(*this == other);
    }

    // Friend declaration for dynamic cast
    template <class Y, class U>
    friend SmartPointer<Y> dynamic_smart_pointer_cast(const SmartPointer<U>& sp);
};

// Dynamic cast for SmartPointer
template <class Y, class U>
SmartPointer<Y> dynamic_smart_pointer_cast(const SmartPointer<U>& sp) {
    SmartPointer<Y> new_sp;
    Y* casted_ptr = dynamic_cast<Y*>(sp.pData);

    if (casted_ptr != 0) {
        // Clean up the default reference count from new_sp
        if (new_sp.reference->Release() == 0) {
            delete new_sp.reference;
        }
        // Adopt the source's pointer and reference count
        new_sp.pData = casted_ptr;
        new_sp.reference = sp.reference;
        new_sp.reference->AddRef();
    }

    return new_sp;
}

#endif // __SMART_POINTER_HEADER__

Notes for C++98 Compatibility

  • We use 0 instead of nullptr (since C++98 doesn't support nullptr)
  • The explicit constructor prevents accidental conversions from raw pointers to SmartPointer
  • The atomic operations (__sync_add_and_fetch) are GCC extensions, which are widely supported in C98 environments where C11 toolchains aren't available

内容的提问来源于stack exchange,提问作者Nathan Owen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:10:08