我在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;
};
问题来自于实施“Edge”课程的时候了。我虽然喜欢这样的东西:
#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;
};
就是这样,构造函数给了我一些问题,经过研究后我认为是因为“Node”不是真正的类,而且“Edge”也被转换为模板。
问题是¿无论如何,Edge可以使用此节点而无需转换为模板吗?
感谢您的时间。
//编辑#1
我希望实现尽可能通用,这就是为什么我认为Edge类应该具有Node类型的属性。
主要栏目如下:
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
答案 0 :(得分:2)
您的成员_leftNode
和_rightNode
需要初始化,但Node
没有默认构造函数。您当前的构造函数不会初始化它们,但会尝试在构造函数体中为它们分配新值。
您可以修改Edge
构造函数,在其成员初始化列表中初始化它们,如下所示:
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)
引用。
答案 1 :(得分:1)
如果您的用例不需要有关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
代替。
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)引用。
答案 2 :(得分:0)
在您使用特定类型对其进行实例化之前,模板化的类不存在。此外,模板Node<int>
与Node<char>
的类型不同。如果希望Edge类能够处理Node
而不将Edge类作为模板类本身,则需要在Edge类中明确指定Node类型,如下所示:
Edge(const Node<int>& leftNode, const Node<int>& rightNode) { ... }
或者您必须将Edge类转换为模板,以便能够一般地处理具有不同类型节点的边。