据我了解,在 C++ 中,派生类不会从基类继承重载的赋值运算符。我在下面编写了一个示例,其中我为基类和派生类显式重载了赋值运算符。在底部的示例输出中,有一个部分:
Index:1 - Base Value:1
Index:1 - Derived Value:2
Index:2 - Base Value:2
Index:2 - Derived Value:2
预期的输出应该是:
Index:1 - Base Value:2
Index:1 - Derived Value:2
Index:2 - Base Value:2
Index:2 - Derived Value:2
这个输出并不意外。我意识到赋值运算符不是继承的。是否有事实上安全/标准的方法让派生类调用基类的赋值运算符?到目前为止,我最好的猜测是让派生类的赋值运算符函数将派生类对象向上转换为基类对象,并将 RHS 分配给 LHS。这是普遍接受的安全方法吗?
如果我使用“建议的解决方案”(页面底部),它会起作用,但这只是因为没有一个运算符被声明为 virtual
。如果我向上转换并使用非虚函数,所使用函数的版本取决于转换,而如果我使用虚函数,所使用的成员函数取决于对象的实际类型而不是它是什么投为。
谢谢。
代码 list
/*******************************************************************************
* Preprocessor Directives
******************************************************************************/
#include <iostream>
using namespace std;
/*******************************************************************************
* Class Declarations and Function Prototypes
******************************************************************************/
class Base {
private:
protected:
public:
int iBInt;
Base(); /* Constructor */
Base(int a); /* Constructor - Set const member */
Base & operator=(const Base& rhs);
virtual ~Base();
};
class Derived : public Base {
private:
protected:
public:
int iDInt;
Derived(); /* Constructor */
Derived(int a); /* Constructor - Set const member */
Derived & operator=(const Derived& rhs);
~Derived();
};
/*******************************************************************************
* Class and Function Definitions
******************************************************************************/
/******************************************************************************/
Base::Base(void) {
cout << __FUNCTION__ << endl;
iBInt = 0;
cout << "iBInt: " << iBInt << endl;
}
/******************************************************************************/
Base::Base(int a) {
cout << __FUNCTION__ << endl;
iBInt = a;
cout << "iBInt: " << iBInt << endl;
}
/******************************************************************************/
Base::~Base(void) {
cout << __FUNCTION__ << endl;
}
/******************************************************************************/
Base& Base::operator=(const Base& rhs) {
cout << "Base::" << __FUNCTION__ << endl;
if (this == &rhs) {
return *this;
}
iBInt = rhs.iBInt;
cout << "iBInt: " << iBInt << endl;
return *this;
}
/******************************************************************************/
Derived::Derived(void) {
cout << __FUNCTION__ << endl;
iDInt = 0;
cout << "iDInt: " << iDInt << endl;
}
/******************************************************************************/
Derived::Derived(int a) : Base(a) {
cout << __FUNCTION__ << endl;
iDInt = a;
cout << "iDInt: " << iDInt << endl;
}
/******************************************************************************/
Derived::~Derived(void) {
cout << __FUNCTION__ << endl;
}
/******************************************************************************/
Derived& Derived::operator=(const Derived& rhs) {
cout << "Derived::" << __FUNCTION__ << endl;
if (this == &rhs) {
return *this;
}
iDInt = rhs.iDInt;
cout << "iDInt: " << iDInt << endl;
return *this;
}
/*******************************************************************************
* Main Entry Point
******************************************************************************/
int main(void) {
int count = 3;
/* Generate objects */
Derived **bArr = new Derived*[count];
for (int i=0; i<count; i++) {
bArr[i] = new Derived(i);
}
/* Set some values via overloaded assignment operator, and print out
* updated values.
*/
for (int i=0; i<count; i++) {
cout << "Index:" << i << " - Base Value:" << bArr[i]->iBInt << endl;
cout << "Index:" << i << " - Derived Value:" << bArr[i]->iDInt << endl;
}
*bArr[1] = *bArr[2];
for (int i=0; i<count; i++) {
cout << "Index:" << i << " - Base Value:" << bArr[i]->iBInt << endl;
cout << "Index:" << i << " - Derived Value:" << bArr[i]->iDInt << endl;
}
/* Cleanup */
for (int i=0; i<count; i++) {
delete bArr[i];
}
delete [] bArr;
return 0;
}
示例输出
Base
iBInt: 0
Derived
iDInt: 0
Base
iBInt: 1
Derived
iDInt: 1
Base
iBInt: 2
Derived
iDInt: 2
Index:0 - Base Value:0
Index:0 - Derived Value:0
Index:1 - Base Value:1
Index:1 - Derived Value:1
Index:2 - Base Value:2
Index:2 - Derived Value:2
Derived::operator=
iDInt: 2
Index:0 - Base Value:0
Index:0 - Derived Value:0
Index:1 - Base Value:1
Index:1 - Derived Value:2
Index:2 - Base Value:2
Index:2 - Derived Value:2
~Derived
~Base
~Derived
~Base
~Derived
~Base
建议的解决方案/编辑
/******************************************************************************/
Derived& Derived::operator=(const Derived& rhs) {
cout << "Derived::" << __FUNCTION__ << endl;
if (this == &rhs) {
return *this;
}
Base* b1 = this;
Base* b2 = (Base*)&rhs;
*b1 = *b2;
iDInt = rhs.iDInt;
cout << "iDInt: " << iDInt << endl;
return *this;
}
最佳答案
我会说直接调用 Base
赋值运算符:
Base::operator =(rhs);
以这种方式调用继承类的赋值运算符比用指针体操调用它要干净和直接得多。
另一种方法是:
static_cast<Base &>(*this) = rhs;
这比使用指针调用运算符更干净,但(IMO)仍然不如显式调用基本运算符重载可读。
关于C++ - 派生类 "inherit"的安全/标准方法是来自基类的重载赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25629498/