C++:纯虚赋值运算符

发布于 2024-09-24 07:25:49 字数 1270 浏览 4 评论 0原文

为什么如果我们在基类中有纯虚拟赋值运算符,然后我们在派生类上实现该运算符,它会在基类上给出链接器错误?

目前我只有以下解释 http://support.microsoft.com/kb/130486 ,它表示该行为是设计使然,因为正常的继承规则不适用

我不清楚,为什么它会按设计生成链接器错误?有人能给我更清楚的解释吗?

编辑:添加了我的简化代码,其中发生了错误:

class __declspec(dllexport) BaseClass {
public:
    int memberA;
    virtual BaseClass& operator=(const BaseClass& rhs) = 0;
};

class __declspec(dllexport) DerivedClass : public BaseClass {
public:
    int memberB;
    DerivedClass():memberB(0) {}
    virtual BaseClass& operator=(const BaseClass& rhs) {
        this->memberA = rhs.memberA;
        this->memberB = 1;
        return *this;
    }
};

int main(void)
{
    DerivedClass d1;
    DerivedClass d2;

    BaseClass* bd1 = &d1;
    BaseClass* bd2 = &d2;

    *bd1 = *bd2;
}

代码将编译没有错误没有 __declspec(dllexport) 和/或 没有基类上的纯虚运算符=声明。

赋值 *bd1 = *bd2; 后,如果没有 __declspec(dllexport),d1::memberB 为 1,但有 __declspec(dllexport) d1 ::memberB 与 __declspec(dllexport) 保持不变

,并且没有纯虚声明,在赋值 *bd1 = *bd2; 后,d1::memberB 保持不变

why if we have pure virtual assignment operator in a base class, then we implement that operator on the derived class, it give linker error on the base class?

currently I only have the following explanation on http://support.microsoft.com/kb/130486 , it said that the behavior is by design since normal inheritance rules does not apply.

it is not clear for me, why is it generate linker error by design? can someone give me more clear explanation about this?

edit: added my simplified code of which the error occured:

class __declspec(dllexport) BaseClass {
public:
    int memberA;
    virtual BaseClass& operator=(const BaseClass& rhs) = 0;
};

class __declspec(dllexport) DerivedClass : public BaseClass {
public:
    int memberB;
    DerivedClass():memberB(0) {}
    virtual BaseClass& operator=(const BaseClass& rhs) {
        this->memberA = rhs.memberA;
        this->memberB = 1;
        return *this;
    }
};

int main(void)
{
    DerivedClass d1;
    DerivedClass d2;

    BaseClass* bd1 = &d1;
    BaseClass* bd2 = &d2;

    *bd1 = *bd2;
}

the code will compile with no errors without __declspec(dllexport) and/or without pure virtual operator= declaration on base class.

without __declspec(dllexport) after assignment of *bd1 = *bd2;, d1::memberB is 1, but with __declspec(dllexport) d1::memberB is left unchanged

with __declspec(dllexport), and without pure virtual declaration, after assignment of *bd1 = *bd2;, d1::memberB is left unchanged

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

枕头说它不想醒 2024-10-01 07:25:49

根据标准第 12.8 节:

13 类 X 的隐式定义的复制赋值运算符执行其子对象的成员赋值。
X 的直接基类首先按照它们在基说明符列表中声明的顺序分配,然后是直接基类
X 的非静态数据成员按照它们在类定义中声明的顺序进行分配。每个子对象
以适合其类型的方式分配:

——如果子对象是类类型,则使用该类的复制赋值运算符(就像通过显式限定一样;
也就是说,忽略更多派生类中任何可能的虚拟重写函数);

子类使用隐式定义的复制赋值运算符,并且基类的复制赋值运算符没有定义,但已声明,因此您会收到链接错误而不是编译错误。

From section 12.8 of the standard:

13 The implicitly-defined copy assignment operator for class X performs memberwise assignment of its subobjects. The
direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list
, and then the immediate
non-static data members of X are assigned, in the order in which they were declared in the class definition. Each subobject
is assigned in the manner appropriate to its type:

— if the subobject is of class type, the copy assignment operator for the class is used (as if by explicit qualification;
that is, ignoring any possible virtual overriding functions in more derived classes);

The subclass is using the implicitly-defined copy assignment operator, and there is no definition of the base class's copy assignment operator, but it is declared, so you get a link error instead of a compilation error.

雪若未夕 2024-10-01 07:25:49

运算符= 不被继承。您的代码在 C++ 中毫无意义,因此编译器可以自由地发出他们想要的任何错误。

从您指向的知识库文章中:http://support.microsoft.com/kb/130486

由于operator=不是继承的,因此基类中operator=的任何声明都是未使用且不必要的。不要在基类中声明operator=。

这可能只是他们编译方式的副作用,他们只是让您知道他们不认为这是一个错误,所以不需要修复它。 “按设计”并不一定意味着他们专门决定这个链接器错误是针对这种情况给出的正确错误消息——代码是错误的,你会得到一个错误,所以从他们的角度来看——他们是完毕。

operator= is not inherited. Your code is meaningless in C++, so compilers are free to issue any error they want for it.

From the KB article you pointed to: http://support.microsoft.com/kb/130486

Since operator= is not inherited, any declaration of operator= in the base class is unused and unnecessary. Do not declare the operator= in the base class.

It's probably just a side-effect of how they compile, and they are just letting you know that they don't consider it a bug, so there is no need to fix it. "By design" doesn't necessarily mean that they specifically decided that this linker error is the right error message to give for this situation -- the code is wrong, you get an error, so from their point of view -- they're done.

只为守护你 2024-10-01 07:25:49

在示例代码中:

class A
{
public :
   // To workaround LNK2001, comment the following line.
   virtual const A& operator=( const A& f ) = 0;
};

class B : public A
{
public :
   const A& operator=( const A& g ) {return g;}
};

B aB1, aB2;

int /*void*/ main( void )
{
   aB2 = aB1;
}

aB2 = aB1 不会调用 const A& B::operator=(const A&),而是调用自动提供的 B& operator=(const B&); 依次使用赋值运算符来分配类的基部分。但当谈到链接时,事实证明这从未实现过。

In the example code:

class A
{
public :
   // To workaround LNK2001, comment the following line.
   virtual const A& operator=( const A& f ) = 0;
};

class B : public A
{
public :
   const A& operator=( const A& g ) {return g;}
};

B aB1, aB2;

int /*void*/ main( void )
{
   aB2 = aB1;
}

the line aB2 = aB1 does not call const A& B::operator=(const A&), but instead calls the automatically supplied B& operator=(const B&); which in turn uses the assignment operator for assigning the base portion of the class. But when it comes to linking, it turns out that that was never implemented.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文