C 类使用模板

C++ class using a template

本文关键字:      更新时间:2023-10-16

i正在实现C 中图的简单限制数据结构。我实现的第一个"类"是"节点"或装饰节点。经过很少的研究,我从课程到模板,就像这样。

template <typename T>
class Node {
public:
Node                    ( T element )           {this->_element=element;}
//Setters
void    heuristic       ( double heuristic )    {this->_heuristic=heuristic;}
void    visited         ( bool visited )        {this->_visited=visited;}
void    element         ( T element )           {this->_element=element;}
void    incrementOrder  ()                      {this->_order++;}
void    decrementOrder  ()                      {this->_order--;}
//Getters
int     order           ()                      {return this->_order;}
double  heuristic       ()                      {return this->_heuristic;}
T       element         ()                      {return this->_element;}
bool    isVisited       ()                      {return this->_visited;}
protected:
double  _heuristic;
bool    _visited;
T       _element;
int     _order;
};

是时候该实施"边缘"类了。我是类似的东西:

#include "Node.hpp"
template <typename T>
class Edge {
public:
Edge    (Node<T>& leftNode, Node<T>& rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;}    
Node<T> leftNode    ()                          {return this->_leftNode;}
Node<T> rightNode   ()                          {return this->_rightNode;}
void    leftNode    (Node<T> leftNode)          {this->_leftNode=leftNode;}
void    rightNode   (Node<T> rightNode)         {this->_rightNode=rightNode;}
protected:
Node<T> _leftNode;
Node<T> _rightNode;
};

就是这样,构造函数给我带来了问题,在研究之后,我相信是因为"节点"不是一个真实的班级,也不是将"边缘"变成模板。

问题是,无论如何,边缘可以使用此节点而不会变成模板?

谢谢您的时间。

//编辑#1

我希望实现尽可能一般,这就是为什么我认为边缘类应该具有属性类型节点。

主要块如下:

int main(){
    Node<int> *n1 = new Node<int>(1);
    Node<int> *n2 = new Node<int>(2);
    Edge<int> *e = new Edge<int>(n1, n2);
    return 0;
}

错误消息是:

g++ -Wall --std=c++11 -Iinclude/ src/Main.cpp -o exe/main
src/Main.cpp: In function ‘int main()’:
src/Main.cpp:11:16: warning: unused variable ‘e’ [-Wunused-variable]
     Edge<int> *e = new Edge<int>(n1, n2);
                ^
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp: In instantiation of ‘Edge<T>::Edge(Node<T>*, Node<T>*) [with T = int]’:
src/Main.cpp:11:40:   required from here
include/Edge.hpp:8:53: error: no matching function for call to ‘Node<int>::Node()’
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                     ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note: candidate: Node<T>::Node(T) [with T = int]
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:17:5: note:   candidate expects 1 argument, 0 provided
include/Node.hpp:14:7: note: candidate: constexpr Node<int>::Node(const Node<int>&)
 class Node {
       ^
include/Node.hpp:14:7: note:   candidate expects 1 argument, 0 provided
include/Node.hpp:14:7: note: candidate: constexpr Node<int>::Node(Node<int>&&)
include/Node.hpp:14:7: note:   candidate expects 1 argument, 0 provided
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:53: error: no matching function for call to ‘Node<int>::Node()’
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                     ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note: candidate: Node<T>::Node(T) [with T = int]
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:17:5: note:   candidate expects 1 argument, 0 provided
include/Node.hpp:14:7: note: candidate: constexpr Node<int>::Node(const Node<int>&)
 class Node {
       ^
include/Node.hpp:14:7: note:   candidate expects 1 argument, 0 provided
include/Node.hpp:14:7: note: candidate: constexpr Node<int>::Node(Node<int>&&)
include/Node.hpp:14:7: note:   candidate expects 1 argument, 0 provided
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:69: error: ambiguous overload for ‘operator=’ (operand types are ‘Node<int>’ and ‘Node<int>*’)
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                                     ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:14:7: note: candidate: Node<int>& Node<int>::operator=(const Node<int>&) <near match>
 class Node {
       ^
include/Node.hpp:14:7: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:69: error: invalid user-defined conversion from ‘Node<int>*’ to ‘const Node<int>&’ [-fpermissive]
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                                     ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note: candidate is: Node<T>::Node(T) [with T = int] <near match>
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:17:5: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:69: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                                     ^
include/Edge.hpp:8:69: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note:   initializing argument 1 of ‘Node<T>::Node(T) [with T = int]’
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:14:7: note: candidate: Node<int>& Node<int>::operator=(Node<int>&&) <near match>
 class Node {
       ^
include/Node.hpp:14:7: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:69: error: invalid user-defined conversion from ‘Node<int>*’ to ‘Node<int>&&’ [-fpermissive]
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                                     ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note: candidate is: Node<T>::Node(T) [with T = int] <near match>
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:17:5: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:69: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                                     ^
include/Edge.hpp:8:69: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note:   initializing argument 1 of ‘Node<T>::Node(T) [with T = int]’
     Node                    ( T element )           {this->_element=element;}
     ^
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:69: error: conversion to non-const reference type ‘class Node<int>&&’ from rvalue of type ‘Node<int>’ [-fpermissive]
     Edge    (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=ri
                                                                     ^
include/Edge.hpp:8:95: error: ambiguous overload for ‘operator=’ (operand types are ‘Node<int>’ and ‘Node<int>*’)
     (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;
                                                                                       ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:14:7: note: candidate: Node<int>& Node<int>::operator=(const Node<int>&) <near match>
 class Node {
       ^
include/Node.hpp:14:7: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:95: error: invalid user-defined conversion from ‘Node<int>*’ to ‘const Node<int>&’ [-fpermissive]
     (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;
                                                                                       ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note: candidate is: Node<T>::Node(T) [with T = int] <near match>
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:17:5: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:95: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
     (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;
                                                                                       ^
include/Edge.hpp:8:95: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note:   initializing argument 1 of ‘Node<T>::Node(T) [with T = int]’
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:14:7: note: candidate: Node<int>& Node<int>::operator=(Node<int>&&) <near match>
 class Node {
       ^
include/Node.hpp:14:7: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:95: error: invalid user-defined conversion from ‘Node<int>*’ to ‘Node<int>&&’ [-fpermissive]
     (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;
                                                                                       ^
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note: candidate is: Node<T>::Node(T) [with T = int] <near match>
     Node                    ( T element )           {this->_element=element;}
     ^
include/Node.hpp:17:5: note:   conversion of argument 1 would be ill-formed:
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:95: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
     (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;
                                                                                       ^
include/Edge.hpp:8:95: error: invalid conversion from ‘Node<int>*’ to ‘int’ [-fpermissive]
In file included from include/Edge.hpp:2:0,
                 from include/Graph.hpp:1,
                 from src/Main.cpp:2:
include/Node.hpp:17:5: note:   initializing argument 1 of ‘Node<T>::Node(T) [with T = int]’
     Node                    ( T element )           {this->_element=element;}
     ^
In file included from include/Graph.hpp:1:0,
                 from src/Main.cpp:2:
include/Edge.hpp:8:95: error: conversion to non-const reference type ‘class Node<int>&&’ from rvalue of type ‘Node<int>’ [-fpermissive]
     (Node<T> *leftNode, Node<T> *rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;
                                                                                       ^
Makefile:19: recipe for target 'default' failed
make: *** [default] Error 1

您的成员_leftNode_rightNode需要初始化,但Node没有 default 构造函数。您当前的构造函数不会初始化它们,而是试图在构造函数主体中分配新值。

您可以修改Edge构造函数以在其成员initializer列表中初始化它们:

Edge(Node<T>& leftNode, Node<T>& rightNode):
     _leftNode(leftNode), _rightNode(rightNode)
{
}    

或者您可以将默认构造函数添加到Node-一个不进行参数。

template <typename T>
class Node {
public:
    Node() = default;
    // ...

此外,您可以使用Node( T element )构造函数进行相同的操作,并在可能的情况下使用const参考,例如Node( const T& element )Edge(const Node<T>& leftNode, const Node<T>& rightNode)

https://godbolt.org/g/r7ms4a

如果您的用例不需要有关element的信息(例如,编写只需访问图形而无需访问其节点数据的编写通用算法(,则可以尝试尝试将数据分开界面。这是一个总体想法:

#include <iostream>
// Note: don't do this
using namespace std;

将节点元数据拆分为非策略类INode

class INode {
public:
    void heuristic(double heuristic) { this->_heuristic = heuristic; }
    void visited(bool visited) { this->_visited = visited; }
    void incrementOrder() { this->_order++; }
    void decrementOrder() { this->_order--; }
    //Getters
    int order() { return this->_order; }
    double heuristic() { return this->_heuristic; }
    bool isVisited() { return this->_visited; }
protected:
    double _heuristic;
    bool _visited;
    int _order;
};

创建一个模板包装器以保存数据

template <typename T>
class Node : public INode {
public:
    Node(T element) { this->_element = element; }
    void element(T element) { this->_element = element; }
    T element() { return this->_element; }
protected:
    T _element;
};

如果Edge不需要了解element,则可以使用INode S。

class Edge {
public:
    //Edge    (Node<T>& leftNode, Node<T>& rightNode) {this->_leftNode=leftNode;this->_rightNode=rightNode;}
    Edge(INode leftNode, INode rightNode)
        : _leftNode(leftNode)
        , _rightNode(rightNode)
    {
    }
    INode leftNode() { return this->_leftNode; }
    INode rightNode() { return this->_rightNode; }
    void leftNode(INode leftNode) { this->_leftNode = leftNode; }
    void rightNode(INode rightNode) { this->_rightNode = rightNode; }
protected:
    INode _leftNode;
    INode _rightNode;
};

您现在可以使用以下内容:

int main()
{
    Node<int> l(1);
    Node<int> r(2);
    Edge edge(l, r);
}

请将其视为伪代码以演示这个想法 - 即使它编译了对象切片的问题。您将要确保您有虚拟类和使用(const(引用。

直到用特定类型实例化模板类。此外,模板Node<int>Node<char>不同。如果您希望Edge类能够处理Node,而无需Edge类是模板类本身,则需要在边缘类中明确指定节点类型,例如:

Edge(const Node<int>& leftNode, const Node<int>& rightNode) { ... }

,或者您必须将边缘类变成模板,以便您能够使用不同类型的节点来处理边缘。

相关文章:
  • 没有找到相关文章