gpt4 book ai didi

c++ - 抽象基类如何避免部分赋值?

转载 作者:搜寻专家 更新时间:2023-10-31 01:46:44 27 4
gpt4 key购买 nike

如《更有效的C++》第33条所说,赋值问题是

//Animal is a concrete class
Lizard:public Animal{};
Chicken:public Animal{};

Animal* pa=new Lizard('a');
Animal* pb=new Lizard('b');
*pa=*pb;//partial assignment

但是,如果我将Animal定义为抽象基类,我们也可以编译运行这句:*pa=*pb。部分分配问题仍然存在。
看我的例子:

#include <iostream> 
class Ab{ private: int a;
double b;
public:
virtual ~Ab()=0;
};
Ab::~Ab(){}

class C:public Ab{
private:
int a;
double b;
};

class D:public Ab{
private:
int a;
double b;
};

int main()
{
Ab *pc=new C();
Ab *pd=new D();
*pc=*pd;
return 0;
}

我错过了什么吗?那么抽象基类的真正含义是什么?

我自己得到了答案。我错过了书中的一段代码。
在基类中使用protected operator=来避免*pa=*pb。使用抽象基类来避免 animal1=animal2。那么唯一允许的表达式是 lizard1=lizard2;chicken1=chicken2;
请看下面的代码:

#include <iostream> 
class Ab{
private:
int a;
double b;
public:
virtual ~Ab()=0;
protected: //!!!!This is the point
Ab& operator=(const Ab&){...}
};
Ab::~Ab(){}

class C:public Ab{
public:
C& operator=(const C&){...}
private:
int a;
double b;
};

class D:public Ab{
public:
D& operator=(const D&){...}
private:
int a;
double b;
};

int main()
{
Ab *pc=new C();
Ab *pd=new D();
*pc=*pd;
return 0;
}

最佳答案

抽象基类在赋值的情况下无能为力,因为基础子对象没有被实例化(抽象类会阻止什么)而是从派生对象中分离出来(即赋值是在已经存在的基础子对象之间完成的).

为了避免这个问题,我能想到的唯一解决办法是

  1. 虚拟化作业
  2. 检查源实例的类型是否正确

在代码中

#include <iostream>

struct Base {
int bx;
Base(int bx) : bx(bx) {}

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

struct A : Base {
int x;
A(int bx, int x) : Base(bx), x(x) {}
A& operator=(const Base& other) {
const A& other_a = dynamic_cast<const A&>(other);
Base::operator=(other);
x = other_a.x;
return *this;
}
};

struct B : Base {
int x;
B(int bx, int x) : Base(bx), x(x) {}
B& operator=(const Base& other) {
const B& other_b = dynamic_cast<const B&>(other);
Base::operator=(other);
x = other_b.x;
return *this;
}
};

dynamic_cast<const A&>(other)如果传递给赋值运算符的对象不是正确的派生类型(它可以是子派生对象,但这在逻辑上对于赋值 source 来说应该是正确的)是将失败的操作。

举个例子:

int main(int argc, const char *argv[]) {

Base *pa1 = new A(1, 2);
Base *pa2 = new A(3, 4);
Base *pb1 = new B(5, 6);
Base *pb2 = new B(7, 8);

*pa1 = *pa2; std::cout << pa1->bx << "/" << dynamic_cast<A*>(pa1)->x << "\n";
*pb1 = *pb2; std::cout << pb1->bx << "/" << dynamic_cast<B*>(pb1)->x << "\n";
std::cout << "Ok so far\n";

*pa1 = *pb1; // Runtime error here (bad cast)

return 0;
}

关于c++ - 抽象基类如何避免部分赋值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20298148/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com