gpt4 book ai didi

c++ - 如何使用类模板删除样板代码?

转载 作者:行者123 更新时间:2023-11-28 04:13:34 25 4
gpt4 key购买 nike

在下面的例子中有一个基类和两个派生类。派生类彼此没有区别,但我包含它只是为了说明可以有多个子类。该代码创建了一个派生类(隐式向上转换,想想工厂设计模式),它被多态地克隆到一个智能指针(就像这里所做的一样 Clone pattern for std::shared_ptr in C++ )然后类的属性被更改以显示克隆已经按预期工作。这运行良好并返回所需的输出“Source:4 Clone:1”。不过,我想知道是否可以删除样板代码?

#include "pch.h"
#include <iostream>

class Node
{
public:
Node(int);
int value;
virtual ~Node() = default;
virtual void set_value(int) = 0;
std::shared_ptr<Node> Clone() const;

private:
virtual Node * CloneImplementation() const = 0;
};

Node::Node(int VALUE) {
value = VALUE;
}

std::shared_ptr<Node> Node::Clone() const {
return std::shared_ptr<Node>(CloneImplementation());
};

class DerivedNode1 : public Node
{
public:
DerivedNode1(int);
void set_value(int);
std::shared_ptr<DerivedNode1> Clone() const;

private:
DerivedNode1 * CloneImplementation() const override;
};

DerivedNode1::DerivedNode1(int VALUE) : Node(VALUE) {
}

std::shared_ptr<DerivedNode1> DerivedNode1::Clone() const {
return std::shared_ptr<DerivedNode1>(CloneImplementation());
};

DerivedNode1 * DerivedNode1::CloneImplementation() const {
return new DerivedNode1(*this);
};

void DerivedNode1::set_value(int NEW_VALUE) {
value = NEW_VALUE;
}

class DerivedNode2 : public Node
{
public:
DerivedNode2(int);
void set_value(int);
std::shared_ptr<DerivedNode2> Clone() const;

private:
DerivedNode2 * CloneImplementation() const override;
};

DerivedNode2::DerivedNode2(int VALUE) : Node(VALUE) {
}

std::shared_ptr<DerivedNode2> DerivedNode2::Clone() const {
return std::shared_ptr<DerivedNode2>(CloneImplementation());
};

DerivedNode2 * DerivedNode2::CloneImplementation() const {
return new DerivedNode2(*this);
};

void DerivedNode2::set_value(int NEW_VALUE) {
value = NEW_VALUE;
}

std::shared_ptr<Node> ImplicitUpCast(int type) {
if (type == 1) {
return std::make_shared<DerivedNode1>(1);
} else {
return std::make_shared<DerivedNode2>(1);
}
}

int main() {
std::shared_ptr<Node> sourceNode1 = ImplicitUpCast(1);
std::shared_ptr<Node> cloneNode1 = sourceNode1->Clone();
sourceNode1->set_value(4);

std::cout << "Source: " << sourceNode1->value << " Clone: " << cloneNode1->value;
}

在每个子类中制作和声明以下方法似乎很乏味,我想要一个解决方法。

std::shared_ptr<DerivedNode1>  DerivedNode1::Clone() const {
return std::shared_ptr<DerivedNode1>(CloneImplementation());
};

DerivedNode1 * DerivedNode1::CloneImplementation() const {
return new DerivedNode1(*this);
};

我的方法是使用一个“中间”类模板,DerivedNode1DerivedNode2 继承并包含这两种方法。这是我的尝试。

#include "pch.h"
#include <iostream>

class Node
{
public:
Node(int);
int value;
virtual ~Node() = default;
virtual void set_value(int) = 0;
std::shared_ptr<Node> Clone() const;

private:
virtual Node * CloneImplementation() const = 0;
};

Node::Node(int VALUE) {
value = VALUE;
}

std::shared_ptr<Node> Node::Clone() const {
return std::shared_ptr<Node>(CloneImplementation());
};


template<class source>
class NodeExtended : public Node
{
public:
NodeExtended(int);
std::shared_ptr<source> Clone() const;
private:
source* CloneImplementation() const override;
};

template<class source>
NodeExtended<source>::NodeExtended(int VALUE) : Node(VALUE) {
}

template<class source>
std::shared_ptr<source> NodeExtended<source>::Clone() const {
return std::shared_ptr<source>(CloneImplementation());
};

template<class source>
source * NodeExtended<source>::CloneImplementation() const {
return new source(*this);
};

class DerivedNode1 : public NodeExtended<DerivedNode1>
{
public:
DerivedNode1(int);
void set_value(int);

};

DerivedNode1::DerivedNode1(int VALUE) : NodeExtended(VALUE) {
}

void DerivedNode1::set_value(int NEW_VALUE) {
value = NEW_VALUE;
}

class DerivedNode2 : public NodeExtended<DerivedNode2>
{
public:
DerivedNode2(int);
void set_value(int);
};

DerivedNode2::DerivedNode2(int VALUE) : NodeExtended(VALUE) {
}

void DerivedNode2::set_value(int NEW_VALUE) {
value = NEW_VALUE;
}

std::shared_ptr<Node> ImplicitUpCast(int type) {
if (type == 1) {
return std::make_shared<DerivedNode1>(1);
} else {
return std::make_shared<DerivedNode2>(1);
}
}

int main() {
//std::shared_ptr<Node> sourceNode1 = ImplicitUpCast(1);
//std::shared_ptr<Node> cloneNode1 = sourceNode1->Clone();
//sourceNode1->set_value(4);

//std::cout << "Source: " << sourceNode1->value << " Clone: " << cloneNode1->value;
}

我在以下行收到错误“NodeExtended::CloneImplementation”:无法将函数定义与现有声明相匹配

source * NodeExtended<source>::CloneImplementation() const {
return new source(*this);
};

我假设这是因为 Node 和 source 不被视为父指针和子指针,并且多态性由于返回类型而崩溃,类似于智能指针在这种情况下可能引发错误的方式。

我不确定如何从这里继续。我认为我对类模板的理解不够好,但没有教程真正涵盖我的用例。

我们将不胜感激。

编辑:

批准的答案找到了主要问题,但我还必须将一些源返回类型更改为节点,它仍然提供所需的行为。这是完整的解决方案。

#include "pch.h"
#include <iostream>

class Node
{
public:
Node(int);
int value;
virtual ~Node() = default;
virtual void set_value(int) = 0;
std::shared_ptr<Node> Clone() const;

private:
virtual Node * CloneImplementation() const = 0;
};

Node::Node(int VALUE) {
value = VALUE;
}

std::shared_ptr<Node> Node::Clone() const {
return std::shared_ptr<Node>(CloneImplementation());
};


template<class source>
class NodeExtended : public Node
{
public:
NodeExtended(int);
std::shared_ptr<source> Clone() const;
private:
Node * CloneImplementation() const override;
};

template<class source>
NodeExtended<source>::NodeExtended(int VALUE) : Node(VALUE) {
}

template<class source>
std::shared_ptr<source> NodeExtended<source>::Clone() const {
return std::shared_ptr<source>(static_cast<source*>(CloneImplementation()));
};

template<class source>
Node * NodeExtended<source>::CloneImplementation() const {
return new source(static_cast<const source&>(*this));
};

class DerivedNode1 : public NodeExtended<DerivedNode1>
{
public:
DerivedNode1(int);
void set_value(int);

};

DerivedNode1::DerivedNode1(int VALUE) : NodeExtended(VALUE) {
}

void DerivedNode1::set_value(int NEW_VALUE) {
value = NEW_VALUE;
}

class DerivedNode2 : public NodeExtended<DerivedNode1>
{
public:
DerivedNode2(int);
void set_value(int);
};

DerivedNode2::DerivedNode2(int VALUE) : NodeExtended(VALUE) {
}

void DerivedNode2::set_value(int NEW_VALUE) {
value = NEW_VALUE;
}

std::shared_ptr<Node> ImplicitUpCast(int type) {
if (type == 1) {
return std::make_shared<DerivedNode1>(1);
} else {
return std::make_shared<DerivedNode2>(1);
}
}

int main() {
std::shared_ptr<Node> sourceNode1 = ImplicitUpCast(1);
std::shared_ptr<Node> cloneNode1 = sourceNode1->Clone();
sourceNode1->set_value(4);

std::cout << "Source: " << sourceNode1->value << " Clone: " << cloneNode1->value;
}

最佳答案

CRTP 的问题是类还不是一个完整的类型。这使得 Clonable 更加困难并且需要一些转换。

template<class source>
class NodeExtended : public Node
{
public:
using Node::Node; // inherit constructors

std::shared_ptr<source> Clone() const
{
return std::shared_ptr<source>(static_cast<source*>(CloneImplementation()));
}
private:
// Cannot use covariant return type as source is not complete.
Node* CloneImplementation() const override
{
return new source(static_cast<const source&>(*this));
}
};

关于c++ - 如何使用类模板删除样板代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57146817/

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