0

假设我们有这两个类,并实现了交换习语。基类的复制构造函数和赋值运算符被删除,因为它没有意义。然而,交换方法被实现,因为它拥有一个成员。

namespace std
{
    template<>
    void swap<Base>(Base& a, Base& b)
    {
        a.swap(b);
    }

    template<>
    void swap<Derived>(Derived& a, Derived& b)
    {
        a.swap(b);
    }
}

class Base
{
public:
    Base(int ID) : ID_(ID) {}
    virtual std::string getString()=0;

    Base(const Base&)=delete;
    operator=(const Base&)=delete;

    void swap(Base& rhs)
    {
        std:swap(ID_, rhs.ID_);
    }
private:
    int ID_;
}

class Derived : public Base
{
public:
    Derived(int ID, bool Value) : Base(ID), Value_(Value) {}
    virtual ~Derived() {}
    Derived(Derived& rhs)
    {
        std::swap(*this, rhs);
    }

    virtual std::string getString() {return Value_ ? "True" : "False"}
    void swap(Derived& lhs, Derived& rhs)
    {
        std::swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs);
        std::swap(lhs.Value_, rhs.Value_);
    }
private:
    bool Value_;
}

正如在许多示例中所看到的,这将是我认为的标准方法。但是,我发现公共 Base::swap 存在问题,因为不能只交换抽象基类!

删除 Base 类的模板并保护 Base::swap 方法不是更好吗:

class Base
{
    ...
protected:
    void swap(Base& rhs, Base &lhs);
}

class Derived : public Base
{
    ...
public:
    void swap(Derived& lhs, Derived& rhs)
    {
        Base::swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs);
        std::swap(lhs.Value_, rhs.Value_);
    }
}

假设有另一个从基类派生的类,第一个实现可以交换 ID,但是派生对象的数据成员将保持不变。

那么,我是否正确地认为从外部交换抽象类是不可能的?

4

1 回答 1

2

基类的复制构造函数和赋值运算符被删除,因为它没有意义。

实际上,这很可怕。现在你变得Derived不可复制了!为什么?没有理由添加此限制。Base在复制层次结构的最基类的上下文中,默认的复制构造函数和赋值运算符是完全合理的。

一旦你撤消了它,就不需要像std::swap(derived1, derived2)已经做正确的事情那样做任何其他事情了。默认移动构造/操作是正确的。让编译器为你做事总是好的。

swap但是,如果您无论如何都想覆盖,那么正确的方法是作为非会员朋友

class Base { 
   ...
   friend void swap(Base& lhs, Base& rhs) {
       using std::swap;
       swap(lhs.ID_, rhs.ID_);
   }
};

class Derived : public Base {
   ...
   friend void swap(Derived& lhs, Derived& rhs) {
       using std::swap;
       swap(static_cast<Base&>(lhs), static_cast<Base&>(rhs));
       swap(lhs.Value_, rhs.Value_);
   }
};

此外,您的Derived复制构造函数没有任何意义。根据我回答的第一段删除它。

于 2015-09-02T21:26:30.370 回答