gpt4 book ai didi

c++ - 用纯虚拟类 copy-and-swap 成语

转载 作者:可可西里 更新时间:2023-11-01 18:37:46 25 4
gpt4 key购买 nike

我正在尝试使用纯虚方法和“ copy-and-swap ”惯用法来实现虚类,但我遇到了一些问题。代码无法编译,因为我正在类 A 的赋值运算符中创建实例,其中包含纯虚方法。

有没有办法使用纯虚方法和copy and swap idiom?

class A
{
public:
A( string name) :
m_name(name) { m_type = ""; }
A( const A & rec) :
m_name(rec.m_name), m_type(rec.m_type) {}
friend void swap(A & lhs, A & rhs)
{
std::swap(lhs.m_name, rhs.m_name);
std::swap(lhs.m_type, rhs.m_type);
}

A & operator=( const A & rhs)
{
A tmp(rhs);
swap(*this, tmp);
return *this;
}

friend ostream & operator<<( ostream & os,A & x)
{
x.print(os);
return os;
}

protected:
virtual void print(ostream & os) =0;

string m_type;
string m_name;
};

class B : A
{
public:
B(string name, int att) :
A(name),
m_att(att)
{
m_type="B";
}

B( const B & rec) :
A(rec),
m_att(rec.m_att) {}

friend void swap(B & lhs, B & rhs)
{
std::swap(lhs.m_att, rhs.m_att);
}

B & operator=( const B & rec)
{
B tmp(rec) ;
swap(*this, tmp);
return *this;
}

private:
virtual void print(ostream & os);

int m_att;

};

错误信息:

In member function ‘A& A::operator=(const A&)’:|
error: cannot declare variable ‘tmp’ to be of abstract type ‘A’|
because the following virtual functions are pure within ‘A’:|
virtual void A::print(std::ostream&)|

最佳答案

正如您的编译器告知您的那样,您不能创建抽象类型的变量。没有办法绕过它。

这给您留下了三个主要选择:

停止使用纯虚函数

首先,您可以摆脱纯虚拟方法,并在每个调用 std::terminate 的方法中提供一个小 stub 。 ,这显然会破坏编译时检测所有(以前的)纯虚拟方法是否在所有派生类中被覆盖。

这将导致 slicing ,因为它只会复制基类,而构成派生类的所有内容都会丢失。

使用不带纯虚函数的 stub 类

与此类似,您可以创建一个派生类,它使用简单的 stub (可能调用 std::terminate)实现所有虚拟方法,并且仅用作“基类的可实例化版本”。

要为此类实现的最重要部分是构造函数,该构造函数采用对基类的 const 引用,因此您可以直接使用它而不是复制基类。这个例子还添加了一个移动构造函数,因为我是一个性能拜物教者。

这会导致相同的 slicing问题作为第一选择。根据您的操作,这可能是您的预期结果。

struct InstantiatableA : public A {
InstantiatableA(A const& rhs) : A(rhs) { }
InstantiatableA(A&& rhs) : A(::std::move(rhs)) { }

void print(ostream&) override { ::std::terminate(); }
};

A& A::operator=(InstantiatableA rhs) {
using ::std::swap;
swap(*this, rhs);
return *this;
}

注意:这真的是一个A类型的变量,虽然我说了做不到。唯一需要注意的是 A 类型的变量存在于 InstantiatableA 类型的变量中!

使用复制工厂

最后,您可以向基类添加一个virtual A* copy() = 0;。您的派生类 B 将必须将其实现为 A* copy() override { return new B(*this); }。需要动态内存的原因是派生类型可能需要比基类任意多的内存。

关于c++ - 用纯虚拟类 copy-and-swap 成语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23497050/

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