类模板代替类名的问题

死咸鱼的成长之路 2017-11-20 12:56:34

代码很长 就不往上黏了 问题就是 template <typename Graph>中的Graph是一个类型名称 ,在这里只有DenseGraph类和SparseGraph类 即有向图和无向图 ,adjIterator是定义在DenseGraph和SparseGraph中的 即类嵌套,但是在上面图片中
typename Graph::adjIterator adj(G, v); 这句话始终报错:

这个程序是 照着视频里写的 后来直接将代码粘过来了 还是这样报错 不知道为什么。

上面是adjIterator类的具体实现 。
最大的问题就是不能实例化出用模板类型代替类的对象 typename Graph::adjIterator adj(G, v); 视频说要加typename 我加不加都实例化不出来对象 望大佬指点
...全文
169 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 9 楼 a673786103 的回复:
[quote=引用 8 楼 hdt 的回复:] 还有 sparsegraph
#ifndef INC_05_DFS_AND_COMPONENTS_SPARSEGRAPH_H #define INC_05_DFS_AND_COMPONENTS_SPARSEGRAPH_H #include "iostream" #include "vector" #include "cassert" using namespace std; //稀疏图 -- 邻接表表示 class SparseGraph{ private: int n,m; bool directed; vector<vector<int>> g; //二维向量(数组) 名字为g public: SparseGraph( int n , bool directed ){ this->n = n; this->m = 0; this->directed = directed; for( int i = 0 ; i < n ; i ++ ) g.push_back( vector<int>() ); } ~SparseGraph(){ } int V(){ return n;} int E(){ return m;} void addEdge( int v , int w ){ assert( v >= 0 && v < n ); //判断如果节点数超范围了 程序终止 assert( w >= 0 && w < n ); /*if ( !hasEdge(v,w)) //去掉这句话 这个图就允许存在平行边 {*/ g[v].push_back(w); //稀疏图存的是节点 代表两个节点有边 if( v != w && !directed ) g[w].push_back(v); m ++; /*}*/ } bool hasEdge( int v , int w ){ for( unsigned int i = 0 ; i < g[v].size() ; i ++ ) //把节点v所有的边都遍历一遍 看是否链接w节点 if( g[v][i] == w ) return true; return false; } //for循环打印法 /* void println(){ for ( int i = 0; i < n ; i ++ ) { for( int j = 0 ; j < n ; j ++ ) { cout << g[i][j] << " "; } cout << endl; } } */ //void println(){ // for( int N = 0 ; N < n ; N ++ ) // { // cout << N << " : " ;//表示第几个节点 // } //} class adjIteragor{ private: SparseGraph& G; int v; int index; //指数 public: adjIteragor( int v , SparseGraph& g ):G(g) { this->v = v; this->index = 0; } int begin(){ index = 0; if( G.g[v].size() ) return G.g[v][index]; } bool end(){ return index >= G.g[v].size(); } int next(){ index ++; if( index < G.g[v].size() ) //这个size为动态数组的容量 因此不一定没一行的size都相等 return G.g[v][index]; return -1; } }; }; #endif // // Created by liuyubobobo on 9/22/16. // #ifndef INC_05_DFS_AND_COMPONENTS_COMPONENTS_H #define INC_05_DFS_AND_COMPONENTS_COMPONENTS_H #include <iostream> #include <cassert> #include "DenseGraph.h" #include "SparseGraph.h" using namespace std; template <class Graph> class Component{ private: Graph &G; bool *visited; int ccount; int *id; void dfs( int v ){ visited[v] = true; id[v] = ccount; typename Graph::adjIterator adj(v,G); for( int i = adj.begin() ; !adj.end() ; i = adj.next() ){ if( !visited[i] ) dfs(i); } } public: Component(Graph &graph): G(graph){ visited = new bool[G.V()]; id = new int[G.V()]; ccount = 0; for( int i = 0 ; i < G.V() ; i ++ ){ visited[i] = false; id[i] = -1; } for( int i = 0 ; i < G.V() ; i ++ ) if( !visited[i] ){ dfs(i); ccount ++; } } ~Component(){ delete[] visited; delete[] id; } int count(){ return ccount; } bool isConnected( int v , int w ){ assert( v >= 0 && v < G.V() ); assert( w >= 0 && w < G.V() ); return id[v] == id[w]; } }; #endif //INC_05_DFS_AND_COMPONENTS_COMPONENTS_H [/quote]多谢多谢 竟然犯这么低级的错误
真相重于对错 2017-11-20
  • 打赏
  • 举报
回复
adj(G, v)---》 adj( v , G );
真相重于对错 2017-11-20
  • 打赏
  • 举报
回复
那个类的构造函数的参数给反了!
真相重于对错 2017-11-20
  • 打赏
  • 举报
回复
adjIteragor ----》 adjIterator
  • 打赏
  • 举报
回复
引用 8 楼 hdt 的回复:
还有 sparsegraph
#ifndef INC_05_DFS_AND_COMPONENTS_SPARSEGRAPH_H #define INC_05_DFS_AND_COMPONENTS_SPARSEGRAPH_H #include "iostream" #include "vector" #include "cassert" using namespace std; //稀疏图 -- 邻接表表示 class SparseGraph{ private: int n,m; bool directed; vector<vector<int>> g; //二维向量(数组) 名字为g public: SparseGraph( int n , bool directed ){ this->n = n; this->m = 0; this->directed = directed; for( int i = 0 ; i < n ; i ++ ) g.push_back( vector<int>() ); } ~SparseGraph(){ } int V(){ return n;} int E(){ return m;} void addEdge( int v , int w ){ assert( v >= 0 && v < n ); //判断如果节点数超范围了 程序终止 assert( w >= 0 && w < n ); /*if ( !hasEdge(v,w)) //去掉这句话 这个图就允许存在平行边 {*/ g[v].push_back(w); //稀疏图存的是节点 代表两个节点有边 if( v != w && !directed ) g[w].push_back(v); m ++; /*}*/ } bool hasEdge( int v , int w ){ for( unsigned int i = 0 ; i < g[v].size() ; i ++ ) //把节点v所有的边都遍历一遍 看是否链接w节点 if( g[v][i] == w ) return true; return false; } //for循环打印法 /* void println(){ for ( int i = 0; i < n ; i ++ ) { for( int j = 0 ; j < n ; j ++ ) { cout << g[i][j] << " "; } cout << endl; } } */ //void println(){ // for( int N = 0 ; N < n ; N ++ ) // { // cout << N << " : " ;//表示第几个节点 // } //} class adjIteragor{ private: SparseGraph& G; int v; int index; //指数 public: adjIteragor( int v , SparseGraph& g ):G(g) { this->v = v; this->index = 0; } int begin(){ index = 0; if( G.g[v].size() ) return G.g[v][index]; } bool end(){ return index >= G.g[v].size(); } int next(){ index ++; if( index < G.g[v].size() ) //这个size为动态数组的容量 因此不一定没一行的size都相等 return G.g[v][index]; return -1; } }; }; #endif // // Created by liuyubobobo on 9/22/16. // #ifndef INC_05_DFS_AND_COMPONENTS_COMPONENTS_H #define INC_05_DFS_AND_COMPONENTS_COMPONENTS_H #include <iostream> #include <cassert> #include "DenseGraph.h" #include "SparseGraph.h" using namespace std; template <class Graph> class Component{ private: Graph &G; bool *visited; int ccount; int *id; void dfs( int v ){ visited[v] = true; id[v] = ccount; typename Graph::adjIterator adj(v,G); for( int i = adj.begin() ; !adj.end() ; i = adj.next() ){ if( !visited[i] ) dfs(i); } } public: Component(Graph &graph): G(graph){ visited = new bool[G.V()]; id = new int[G.V()]; ccount = 0; for( int i = 0 ; i < G.V() ; i ++ ){ visited[i] = false; id[i] = -1; } for( int i = 0 ; i < G.V() ; i ++ ) if( !visited[i] ){ dfs(i); ccount ++; } } ~Component(){ delete[] visited; delete[] id; } int count(){ return ccount; } bool isConnected( int v , int w ){ assert( v >= 0 && v < G.V() ); assert( w >= 0 && w < G.V() ); return id[v] == id[w]; } }; #endif //INC_05_DFS_AND_COMPONENTS_COMPONENTS_H
真相重于对错 2017-11-20
  • 打赏
  • 举报
回复
还有 sparsegraph
真相重于对错 2017-11-20
  • 打赏
  • 举报
回复
把component类申明贴出来
  • 打赏
  • 举报
回复
引用 5 楼 a673786103 的回复:
[quote=引用 4 楼 hdt 的回复:] 你的代码不全,我无法详细给你说清楚 只能凭有限的信息讲一下。 typename Graph::XXXX adj() 这句话的意思是 XXXX是Graph的内嵌的一个类型 如果不加typename ,XXX可能是Graph的一个static成员,加了,就代表XXX是一个类型。因为前面有Graph::所以它是Graph内部定义的,因为Graph是模板参数 所以不能直接实例化 看错误提示,似乎是你没有把adjIterator 包含在Graph参数内部。
#pragma once #include "iostream" #include "vector" #include "cassert" using namespace std; //稠密图 -- 邻接矩阵表示 class DenseGraph{ private: int n , m; //节点和边的个数 vector<vector<bool>> g; //创建一个二维向量 相当于二维数组 里面的元素都是bool类型 bool derected; public: DenseGraph( int n , bool derected ){ this->n = n; //每次创建对象时都用this给自己赋初值 this->m = 0; this->derected = derected; for( int i = 0 ; i < n ; i ++ ) g.push_back( vector<bool>( n , false) ); //给n*n容器全部元素赋值false } ~DenseGraph(){ } int V(){ return n; } //得到节点个数 int E(){ return m; } //得到边的个数 void addEdge( int v , int w ){ //向两个节点中添加边 assert( v >= 0 && v <= n ); assert( w >= 0 && w <= n ); if( hasEdge( v , w ) ) //如果这两个节点已经有边了 就不需要添加了 这句话加上就没有平行边的存在了 return; //稠密图存的是真假值 g[v][w] = true; if( !derected ) //如果是无向图 则两边都有添加 g[w][v] = true; m ++; } bool hasEdge( int v , int w ){ assert( v >= 0 && v <= n ); assert( w >= 0 && w <= n ); return g[v][w]; } class adjIterator{ private: int v; int index; DenseGraph& D; public: adjIterator( int v , DenseGraph& dense):D(dense) //因为 adjIterator中含有DenseGraph类的引用对象D 所以要用形参初始化这个对象 实参的类型也是DenseGraph { this->v = v; this->index = 0; } int begin(){ index = -1; return next(); } int next(){ for( index += 1 ; index < D.V() ; index ++ ) if( D.g[v][index] ) //判断第v行第index列是否为ture 如果是ture 说明两个节点之间有边 返回这个列坐标(即这个节点) return index; return -1; //如果在这一行中都为false 则这个节点不跟其他任意一个节点有边 } bool end(){ return index >= D.V(); // D.()为节点总是 虽然是矩阵 但是是动态数组 行列不一定相等 } }; };[/quote] int main() { int n = 10; int m = 50; SparseGraph ss( n , false ); for( int i = 0 ; i < m ; i ++ ) ss.addEdge( rand()%n , rand()%n ); Component<SparseGraph> com1(ss); return 0; }这个是完整类和一个主函数的测试 大佬帮改一下
  • 打赏
  • 举报
回复
引用 4 楼 hdt 的回复:
你的代码不全,我无法详细给你说清楚 只能凭有限的信息讲一下。 typename Graph::XXXX adj() 这句话的意思是 XXXX是Graph的内嵌的一个类型 如果不加typename ,XXX可能是Graph的一个static成员,加了,就代表XXX是一个类型。因为前面有Graph::所以它是Graph内部定义的,因为Graph是模板参数 所以不能直接实例化 看错误提示,似乎是你没有把adjIterator 包含在Graph参数内部。
#pragma once #include "iostream" #include "vector" #include "cassert" using namespace std; //稠密图 -- 邻接矩阵表示 class DenseGraph{ private: int n , m; //节点和边的个数 vector<vector<bool>> g; //创建一个二维向量 相当于二维数组 里面的元素都是bool类型 bool derected; public: DenseGraph( int n , bool derected ){ this->n = n; //每次创建对象时都用this给自己赋初值 this->m = 0; this->derected = derected; for( int i = 0 ; i < n ; i ++ ) g.push_back( vector<bool>( n , false) ); //给n*n容器全部元素赋值false } ~DenseGraph(){ } int V(){ return n; } //得到节点个数 int E(){ return m; } //得到边的个数 void addEdge( int v , int w ){ //向两个节点中添加边 assert( v >= 0 && v <= n ); assert( w >= 0 && w <= n ); if( hasEdge( v , w ) ) //如果这两个节点已经有边了 就不需要添加了 这句话加上就没有平行边的存在了 return; //稠密图存的是真假值 g[v][w] = true; if( !derected ) //如果是无向图 则两边都有添加 g[w][v] = true; m ++; } bool hasEdge( int v , int w ){ assert( v >= 0 && v <= n ); assert( w >= 0 && w <= n ); return g[v][w]; } class adjIterator{ private: int v; int index; DenseGraph& D; public: adjIterator( int v , DenseGraph& dense):D(dense) //因为 adjIterator中含有DenseGraph类的引用对象D 所以要用形参初始化这个对象 实参的类型也是DenseGraph { this->v = v; this->index = 0; } int begin(){ index = -1; return next(); } int next(){ for( index += 1 ; index < D.V() ; index ++ ) if( D.g[v][index] ) //判断第v行第index列是否为ture 如果是ture 说明两个节点之间有边 返回这个列坐标(即这个节点) return index; return -1; //如果在这一行中都为false 则这个节点不跟其他任意一个节点有边 } bool end(){ return index >= D.V(); // D.()为节点总是 虽然是矩阵 但是是动态数组 行列不一定相等 } }; };
真相重于对错 2017-11-20
  • 打赏
  • 举报
回复
你的代码不全,我无法详细给你说清楚 只能凭有限的信息讲一下。 typename Graph::XXXX adj() 这句话的意思是 XXXX是Graph的内嵌的一个类型 如果不加typename ,XXX可能是Graph的一个static成员,加了,就代表XXX是一个类型。因为前面有Graph::所以它是Graph内部定义的,因为Graph是模板参数 所以不能直接实例化 看错误提示,似乎是你没有把adjIterator 包含在Graph参数内部。
  • 打赏
  • 举报
回复
引用 2 楼 hdt 的回复:
adj(G, v)---》 adj( v , G );
那个改过过来了 还是出现那中错误

64,659

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧