如何使用类模板删除样板代码?
How to use class templates to remove boiler plate code?
在下面的示例中,有一个基类和两个派生类。派生类彼此没有什么不同,但我包含它只是为了说明可以有多个子类。该代码创建一个派生类(隐式向上转换,想想工厂设计模式),该类以多态方式克隆到智能指针(与此处所做的完全一样 克隆 std::shared_ptr 在 C++ 中),然后更改类的属性以显示克隆已按预期工作。这运行良好并返回所需的输出"源:4 克隆: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);
};
我的方法是使用一个"中间"类模板,该模板DerivedNode1
和DerivedNode2
继承自并包含这两种方法。这是我的尝试。
#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;
}
我在下一行收到错误"节点扩展::克隆实现":无法将函数定义与现有声明匹配">
source * NodeExtended<source>::CloneImplementation() const {
return new source(*this);
};
我假设这是因为 Node 和源代码不被视为父指针和子指针,并且多态性由于返回类型而崩溃,类似于智能指针在这种情况下可能引发错误的方式。
我不确定如何从这里继续。我认为我对类模板的理解不够好,但没有教程真正捕捉到我的用例。
任何和所有的帮助将不胜感激。
编辑:
批准的答案找到了主要问题,但我还必须将一些源返回类型更改为仍然提供所需行为的节点。这是完整的解决方案。
#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 的问题在于类还不是一个完整的类型。 这使得可克隆更加困难,并且需要一些强制转换。
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));
}
};
std::shared_ptr<DerivedNode1> DerivedNode1::Clone() const
,std::shared_ptr<DerivedNode2> DerivedNode2::Clone() const
示例中未调用。没有这些功能,一切正常。在函数中的模板示例中
template<class source>
source * NodeExtended<source>::CloneImplementation() const {
return new source(*this);
};
您尝试调用source(NodeExtended &)
构造函数。你需要类似的东西
return new source(*static_cast<const source*>(this));
那么一切都应该工作。
- 为什么示例代码访问IUnknown中已删除的内存
- 你能检查一下为什么在这个代码中从链接列表中删除项目不起作用吗
- 从 C 样式字符串中删除子字符串 "in place" 在C++代码中
- 是否可以使用 C++ 中的模板减小删除代码大小
- 删除C++继承中虚拟类成员的代码重复
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- 删除继承中的代码重复?
- 从排序数组中删除重复项,具有不同代码方式的相同解决方案具有不同的输出
- G++ 发出警告,要求删除一个代码的数组,但不删除另一个代码的数组
- 删除原子多线程代码中的容器
- 使用 ostream 变量删除代码重复
- 可视代码 删除函数括号内的空格
- Qt创建者-如何删除Clang代码模型
- 更正代码c++指针并删除
- 有没有一种预处理器的方法可以从调试符号中删除代码段
- 删除被注释掉的代码,而不是实际的赞美
- 在 cpp 中验证路径:无法使用 ASCII 代码删除特殊字符
- 旧项目中的重复代码删除策略
- 应由库或客户端代码删除已加载库中的对象实例
- 内联和死代码删除优化是否可以阻止模板实例化