有没有一种方法可以通过值将纯抽象类的所有子类传递给C ++中的函数?

时间:2020-07-03 11:51:18

标签: c++

说我有2个类AB,其中A是具有纯虚函数的纯抽象类,并且B继承自A和实现纯虚函数。如果我有一个函数g(),我想按值将A的子类的任何实例传递给(这样我就可以对其进行更改而无需更改原始实例),您将如何做? 我知道以下代码不符合我的目的:

void g(A myObject) {} //doesn't work since A contains a pure virtual function

void g(A* myObject) {} //code compiles, but changes the original instance 

我是否只需复制实例并为其创建一个指针,然后传递给上述函数?还是有一种更清洁的方法来做到这一点?

2 个答案:

答案 0 :(得分:2)

我认为这里的最佳做法是利用clone()方法:

#include <iostream>
#include <memory>

class Base
{
public:
    virtual void set_str(std::string) = 0;
    virtual void print() = 0;
    virtual std::unique_ptr<Base> clone() = 0;
};

class Derived: public Base
{
private:
    std::string _str;
public:
    std::unique_ptr<Base> clone() override { 
        return std::make_unique<Derived>(*this); 
    }
    void set_str(std::string str) override {
        this->_str = str;
    }
    void print() override {
        std::cout << this->_str << std::endl;
    }
};

void foo(std::unique_ptr<Base> obj) {
    obj->set_str("inside");
    obj->print();
}

int main() {
    Derived obj;
    obj.set_str("outside");
    foo(obj.clone());
    obj.print();
    return 0;
}

答案 1 :(得分:1)

如果确实是A中的纯虚函数,则阻止复制的原因。如果可以从其子类创建A复制,则将原始对象切片,并且仅将字段保留在A中。

如果要防止修改,可以:

  • 用引发异常的函数代替纯虚函数。如果您尝试在非子类对象上使用该函数,则A类将变为可创建的,但仍然会中断。
  • 使用上面定义的功能在层次结构中插入A1类,并在g中使用它

这两种方法都会创建原始对象的副本并传递(切片的)副本

您还可以使用const引用:

void g(const A& myObject);

这将传递对原始对象的引用,但是如果您尝试对其进行修改,则编译器将引发错误。