簡體   English   中英

重載abstract operator =時Clang鏈接器錯誤

[英]Clang linker error when overloading abstract operator=

VisualStudio 2013編譯器處理以下代碼就好了,但是clang 5.0和6.2給我一個鏈接器錯誤:

#include <memory>

using namespace::std;

class IBase
{
public:
    virtual IBase& operator=(const IBase& other) = 0;
};

class Base : virtual public IBase
{
public:
    Base& operator=(const IBase& other) override
    {
        const Base& b = dynamic_cast<const Base&>(other);
        return *this = b;
    }

    virtual Base& operator=(const Base& other)
    {
        return *this;
    }
};

class IDerived : virtual public IBase
{
};

class Derived : public IDerived, public Base
{
public:
    using Base::operator=;

};

int main(int argc, const char * argv[]) {
    shared_ptr<Derived> d1 = make_shared<Derived>();
    shared_ptr<Derived> d2 = make_shared<Derived>();
    *d2 = *d1;
}

這是構建日志輸出:

Ld /Users/Jennifer/Library/Developer/Xcode/DerivedData/Operator-bjjgcoxcziyegjgmazknrandutqz/Build/Products/Debug/Oper normal x86_64
    cd /Users/Jennifer/Documents/Operator
    export MACOSX_DEPLOYMENT_TARGET=10.9
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -L/Users/Jennifer/Library/Developer/Xcode/DerivedData/Operator-bjjgcoxcziyegjgmazknrandutqz/Build/Products/Debug -F/Users/Jennifer/Library/Developer/Xcode/DerivedData/Operator-bjjgcoxcziyegjgmazknrandutqz/Build/Products/Debug -filelist /Users/Jennifer/Library/Developer/Xcode/DerivedData/Operator-bjjgcoxcziyegjgmazknrandutqz/Build/Intermediates/Operator.build/Debug/Oper.build/Objects-normal/x86_64/Oper.LinkFileList -mmacosx-version-min=10.9 -stdlib=libc++ -Xlinker -dependency_info -Xlinker /Users/Jennifer/Library/Developer/Xcode/DerivedData/Operator-bjjgcoxcziyegjgmazknrandutqz/Build/Intermediates/Operator.build/Debug/Oper.build/Objects-normal/x86_64/Oper_dependency_info.dat -o /Users/Jennifer/Library/Developer/Xcode/DerivedData/Operator-bjjgcoxcziyegjgmazknrandutqz/Build/Products/Debug/Oper

Undefined symbols for architecture x86_64:
  "IBase::operator=(IBase const&)", referenced from:
      IDerived::operator=(IDerived const&) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

IBase::operator=(IBase const&)Base中定義, Derived繼承自, Derived using Base::operator=因此它應該Derived定義,而不是由默認賦值運算符覆蓋。

我找到的一個解決方案是刪除IBase::operator=方法,但這並不理想,因為它是任何繼承類需要實現的方法。

有誰知道有什么區別以及如何解決它? 如果可能的話,我想保留IBase::operator=方法。

問題是using聲明不算作用戶聲明的賦值運算符[namespace.udecl]

4 - [...]如果從基類帶入賦值類作用域的賦值運算符具有派生類(12.8)的復制/移動賦值運算符的簽名,則using-declaration本身不會抑制隱式派生類賦值運算符的聲明[...]

(在任何情況下, using Base::operator=為您提供一個賦值運算符,其參數類型為Base const& ,它不是一個有資格作為復制賦值運算符的參數類型[class.copy] / 17 - TT&T const&等)

因為Derived沒有用戶聲明的復制賦值運算符,所以會自動生成一個,最終調用IDerived::operator=調用IBase::operator= 請注意,自動生成的復制賦值運算符會調用忽略虛擬覆蓋的子對象復制賦值運算符:

每個子對象都以適合其類型的方式分配:

  • 如果子對象是類類型,就好像通過調用operator=將子對象作為對象表達式而x的對應子對象作為單個函數參數(就像通過顯式限定;即忽略任何可能的虛擬覆蓋函數在更多派生類中); [...]

修復就是寫:

    Base& operator=(Derived const& other) { return Base::operator=(other); }

請注意,MSVC 2015會拒絕您的代碼,但可以使用上述修復程序:

main.cpp(36): warning C4250: 'Derived': inherits 'Base::Base::operator =' via dominance
main.cpp(14): note: see declaration of 'Base::operator ='
main.obj : error LNK2019: unresolved external symbol "public: virtual class IBase & __thiscall IBase::operator=(class IBase const &)" (??4IBase@@UAEAAV0@ABV0@@Z) referenced in function "public: class IDerived & __thiscall IDerived::operator=(class IDerived const &)" (??4IDerived@@QAEAAV0@ABV0@@Z)
main.exe : fatal error LNK1120: 1 unresolved externals

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM