C++抽象类和多态性

C++ abstract class and polymorphism

本文关键字:多态性 抽象类 C++      更新时间:2023-10-16

[更新]我很难使用抽象类,这是我的代码(简单模型):

class A{
  public:
    virtual ~A(void){};
    virtual void print() const = 0;
};
class B : public A{
  public:
    void print() const{cout << x << endl;}
  private:
    int x;
};
class C : public A{
  public:
    void print() const{cout << x << endl;}
  private:
    double x;
};
class X{
  public:
    X(void){
      array = new A * [20]; 
    }
    void Add(const A & src){
      array[someindex] = &src; //Fpermissive, cannot convert const A * to A *
    }; 
  private:
    A ** array; 
};
int main(int argc, char const *argv[]){
  X obj;
  obj.Add(B(9)); //B.x = 9
  obj.Add(C(3.3333)); // C.x = 3.3333
  return 0;
}

如何将数组中的B和C存储在X中?如何使src非常量?有可能吗?谢谢你的回复。我无法修改main。我不想为B类或C类的参数做一个方法Add…

好的,目标是,我必须将对象BC存储在X中,并且我不能修改main函数。BC的对象具有非常相似的方法。

如何将B和C存储在X中的数组中

你不能。只能存储指向它们的指针,并且只有在分配了存储它们的空间之后。

如何使src非常量

大概,您是"被迫"将const添加到X::add()的参数声明中的,因为您传递的是临时变量。您需要传入l-value的地址。

void X::Add( A *src ) { array[someindex] = src; }
B   b(9);
X.Add( &b );
C   c(3.3333);
X.Add( &c ); 

有可能吗

是的,使用const_cast<>,但在这种情况下,这会导致灾难。你的根本问题是你试图存储临时地址。当你做这样的事情时:

X.Add(B(9)); // B will be destroyed when the execution of this statement ends.

假设找到了一种方法,那么最终存储在数组中的将是一个指向垃圾的指针。

UPDATE:根据注释中的交换,似乎需要保存传递给X::Add()方法的const A& src项的副本。通过基类引用或指针进行复制需要一个虚拟的"clone()"方法,其特定目的是在运行时调用子类实现。

class A {
...
virtual A* clone() const = 0;
...
};
class B : public A {
...
// Note signature: this works due to return type covariance
B* clone() const { return new B(*this); } 
...
};
// similarly for class C and others
// use it like this
class X {
...
void Add(const A & src){ array[someindex] = src.clone(); }
...
};

当然,完成后,您必须注意释放这些对象。

当您创建obj时,A**只是一个指向任何地方的小指针,因为您需要初始化它。您可以使用共享指针和向量,这将允许您存储对对象的引用,并避免处理删除

你可以用这种方式申报X

class X{
  public:
    void Add(const shared_ptr<A> & src){ array.push_back(src); };
  private:
    vector<shared_ptr<A>> array; 
};

这将允许任意数量的对象存储到数组中,并避免处理数组,这更简单

你可以这样使用

int main(int argc, char const *argv[]){
  X obj;
  shared_ptr<B> shrdB(new B(9));
  shared_ptr<C> shrdC(new C(3.3333));
  obj.Add(std::dynamic_pointer_cast<A>(shrdB));
  obj.Add(std::dynamic_pointer_cast<A>(shrdC));
  return 0;
}