首页 > 解决方案 > 复制构造抽象类型的数据成员

问题描述

考虑以下场景:

class AbsBase {
public:
    virtual double foo() = 0;
};

class Concrete1 : public AbsBase {
public:
    double foo() {
        return 1;
    }
};

class Concrete2 : public AbsBase {
public:
    double foo() {
        return 2;
    }
};

struct Config {
    /**
     * Must use a pointer to `AbsBase`, since it is an abstract base class, 
     * and the concrete instances could be of either of the derived classes.
     */
    AbsBase* thing;

    void setThing(AbsBase* t) {
        thing = t;
    }
};

行得通,但如果thing是传递给的参数的副本,我会更喜欢它setThing。即如果thing是类型Concrete1(而不是抽象基类),我可以做这样的事情:

Concrete1 thing;
void setThing(const Concrete1& t) {
    thing = Concrete1(t);
}

但是,如果不实例化抽象类型的对象(这是非法的),我看不到实现这一目标的方法。有任何想法吗?

标签: c++abstract-classbase-class

解决方案


您可以使用模板函数来实现所需的行为。我建议也使用它std::unique_ptr来防止内存问题。

class AbsBase {
public:
    virtual ~AbsBase() = default;
    virtual double foo() = 0;
};

class Concrete1 : public AbsBase {
public:
    double foo() {
        return 1;
    }
};

class Concrete2 : public AbsBase {
public:
    double foo() {
        return 2;
    }
};

struct Config {
    /**
     * Must use a pointer to `AbsBase`, since it is an abstract base class, 
     * and the concrete instances could be of either of the derived classes.
     */
    std::unique_ptr<AbsBase> thing;

    template <typename T>
    void setThing(const T& t) {
        static_assert(std::is_base_of<AbsBase, T>::value, "T must inherit AbsBase");
        static_assert(std::is_copy_constructible<T>::value, "T must be copy-constructible");
        thing.reset(new T{t});
    }

    void test()
    {
        std::cout << (thing?thing->foo():0.0) << std::endl;
    }
};

https://gcc.godbolt.org/z/fID5UM


推荐阅读