当前位置:  开发笔记 > 编程语言 > 正文

重载abstract operator =时Clang链接器错误

如何解决《重载abstractoperator=时Clang链接器错误》经验,为你挑选了1个好方法。

VisualStudio 2013编译器处理以下代码就好了,但是clang 5.0和6.2给我一个链接器错误:

#include 

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(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 d1 = make_shared();
    shared_ptr d2 = make_shared();
    *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&)在定义BaseDerived由继承,并且Derivedusing Base::operator=因此它为被定义Derived,而不是默认的赋值运算符重载.

我找到的一个解决方案是删除IBase::operator=方法,但这并不理想,因为它是任何继承类需要实现的方法.

有谁知道有什么区别以及如何解决它?IBase::operator=如果可能的话,我想保留这个方法.



1> ecatmur..:

问题是using声明不算作用户声明的赋值运算符[namespace.udecl]:

4 - [...]如果从基类带入赋值类作用域的赋值运算符具有派生类(12.8)的复制/移动赋值运算符的签名,则using-declaration本身不会抑制隐式派生类赋值运算符的声明[...]

(在任何情况下,using Base::operator=为您提供了参数类型一个赋值操作符Base const&,这是不参数类型资格作为拷贝赋值运算符之一[class.copy]/17 - ,,T 等)T&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

推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有