"other function name" C++ 中对 "function name" 的未定义引用
undefined reference to "function name" in "other function name" C++
作为项目的一部分,我正在尝试从 Tree cpp 文件调用函数到 Graph cpp
但是编译器给我一个错误,说我调用的函数没有定义
两天来我一直在尝试解决这个问题但没有成功
我得到的错误是:
bin/Graph.o: In function `Graph::BFS(Session&, int)':
/home/spl211/CLionProjects/Assign1/src/Graph.cpp:24: undefined reference to `Tree::createTree(Session const&, int)'
/home/spl211/CLionProjects/Assign1/src/Graph.cpp:39: undefined reference to `Tree::createTree(Session const&, int)'
这是我的图形 cpp:谁实现了调用 createTree 的 BFS 算法(问题出在哪里)
#include "../include/Graph.h"
#include "../include/Tree.h"
class Tree;
//--constructor--//
Graph::Graph():edges(),size(),neighbours(),infV(){}
Graph::Graph(std::vector<std::vector<int>> matrix) : edges({{}}), size(0), neighbours({}), infV({}) {
edges = matrix;
size = edges.size();
neighbours = matrix;
for (int i = 0; i < edges.size(); i++) {
infV[i] = 0;
}
};
//--getter--//
std::vector<std::vector<int>> Graph::getEdg()const{
return edges;
};
// --function--//
int Graph::BFS(Session &session, int node) {
Tree *BfsTree = Tree::createTree(session, node);
//--build bfs--//
std::queue<Tree *> que;
std::vector<bool> visited;
for (int i = 0; i < size; i++) {
visited.push_back(false);
}
que.push(BfsTree);
visited[node] = true;
while (!que.empty()) {
Tree *curr_root = que.front();
int nodeId = curr_root->getNode();
que.pop();
for (int j = 0; j < edges[nodeId].size(); j++) {
if (edges[nodeId][j] == 1 && !visited[j]) { //if they are neighbours
Tree *child = Tree::createTree(session, j); //create new child
curr_root->addChild(child); //add the child to the tree
que.push(child); //add the child to que
visited[j] = true; //mark him as visited
}
}
}
//--end of bfs--//
//--now we have shortest path tree for our sick node--//
int output = BfsTree->traceTree();
delete (BfsTree);
return output;
}
void Graph::infectNode(int nodeInd) {
infV[nodeInd] = 1;
};
bool Graph::isInfected(int nodeInd) {
return infV[nodeInd] == 1;
};
这是我的 Tree cpp,它实现了 createTree:
#include "../include/Tree.h"
#include "../include/Session.h"
#include <vector>
//--constructor--//
Tree::Tree():node(0),children(){};
Tree::Tree(int rootLabel):node(0),children({}){
node = rootLabel;
}
//--destructor--//
Tree::~Tree(){
for(Tree* tree:children){
delete(tree);
tree= nullptr;
}
};
//----------------RULE OF 5------------------//
//--copy constructor--//
Tree::Tree(const Tree &other):node(0),children(){
node = other.getNode();
for(Tree* child:other.children){
Tree* clone = child->clone();
children.push_back(clone);
}
}
//--copy assignment operator--//
const Tree& Tree::operator=(const Tree& other){
if(this==&other){return *this;}
for(Tree* child:children){
delete (child);
}
for(Tree* child:other.children){
Tree* clone = child->clone();
children.push_back(clone);
}
node = other.getNode();
}
//--move constructor--//
Tree::Tree(Tree&& other){
node = other.getNode();
for(Tree* tree:other.children){
addChild(tree);
tree= nullptr;
}
}
//--move assignment operator--//
const Tree& Tree::operator=(Tree& other){
if(this==&other){return *this;}
node = other.getNode();
for(Tree* child:children){
delete (child);
}
for(Tree* tree:other.children){
addChild(tree);
tree= nullptr;
}
}
//----------------------------------------//
//---FUNCTIONS---//
//--getters--//
int Tree::getNode()const{
return this->node;
}
std::vector<Tree*> Tree::getChildren(){
return children;
};
//--setters--//
void Tree::setNode(int node){
this->node = node;
};
//-add children--//
void Tree::addChild(const Tree& child){
Tree* clone = child.clone();
children.push_back(clone);
};
void Tree::addChild(Tree* child){
children.push_back(child);
};
//--create tree--//
static Tree* createTree(const Session& session, int rootLabel){
if(session.getTreeType()==Cycle){
return new CycleTree(rootLabel,session.getCycle());
}
if(session.getTreeType()==MaxRank){
return new MaxRankTree(rootLabel);
}
if(session.getTreeType()==Root){
return new RootTree(rootLabel);
}
};
//--max function--//
void Tree::maxChild(Tree* tree,int *max,int *node){
if(this->getChildren().size()>*max){
*(max) = getChildren().size();
*(node)=this->getNode();
}
if(tree->getChildren().size()>0){
for(Tree* child:this->getChildren()){
maxChild(child,max,node);
}
}
}
//------------inherent------------//
//--cycle--//
CycleTree::CycleTree(int rootLabel, int currCycle):Tree(rootLabel),currCycle(currCycle){} ;
int CycleTree::traceTree(){
int curr_node = this->getNode();
Tree* curr_tree =this;
int cycleCount=currCycle;
while(cycleCount>=0&&curr_tree->getChildren().size()>0){
curr_tree = curr_tree->getChildren()[0];
curr_node = curr_tree->getNode();
cycleCount--;
}
return curr_node;
};
Tree* CycleTree::clone()const{return new CycleTree(*this);};
//--max--//
MaxRankTree::MaxRankTree(int rootLabel):Tree(rootLabel){};
int MaxRankTree::traceTree(){
int index =this->getNode();
int* node = &index;
int _max = this->getChildren().size();
int *max = &_max;
for(Tree* child:this->getChildren()){
maxChild(child,max,node);
}
return *node;
};
Tree* MaxRankTree::clone()const{return new MaxRankTree(*this);};
//--root--//
RootTree::RootTree(int rootLabel):Tree(rootLabel){};
int RootTree::traceTree(){return this->getNode();};
Tree* RootTree::clone()const{return new RootTree(*this);};
这是我的 make 文件:
# define some Makefile variables for the compiler flags
# to use Makefile variables later in the Makefile: $()
CC = g++
CFLAGS = -g -Wall -Weffc++ -std=c++11
# All Targets
all:Assign1
# Tool invocations
#Executable
Assign1:bin/main.o bin/Agent.o bin/Graph.o bin/Session.o bin/Tree.o
@echo 'Building target: Assign1'
@echo 'Invoking: C++ Linker'
$(CC) -o bin/main bin/Agent.o bin/Graph.o bin/Session.o bin/Tree.o
@echo 'Finished building target: Assign1'
@echo ' '
#Depends on the source and header files
bin/main.o: src/main.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/main.o src/main.cpp
#Depends on the source and header files
bin/Agent.o: src/Agent.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Agent.o src/Agent.cpp
#Depends on the source and header files
bin/Graph.o: src/Graph.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Graph.o src/Graph.cpp
#Depends on the source and header files
bin/Session.o: src/Session.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Session.o src/Session.cpp
#Depends on the source and header files
bin/Tree.o: src/Tree.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Tree.o src/Tree.cpp
#CLean the build directory
clean:
rm -f bin/*
我明白了,你的方法:
static Tree* createTree(const Session& session, int rootLabel){
在您的 cpp 文件中是静态的。因此它在其他文件中是不可见的。
您可能打算创建以下方法:
Tree* Tree::createTree(const Session& session, int rootLabel){
同一个正文,但签名应该是第二个
您将 createTree
定义为:
static Tree* createTree(...)
这定义了一个 non-成员函数,内部链接对其他翻译单元不可见。
如果它应该是静态 member 函数,则将其定义为成员函数(但没有 static
关键字):
Tree* Tree::createTree(...)
作为项目的一部分,我正在尝试从 Tree cpp 文件调用函数到 Graph cpp 但是编译器给我一个错误,说我调用的函数没有定义 两天来我一直在尝试解决这个问题但没有成功
我得到的错误是:
bin/Graph.o: In function `Graph::BFS(Session&, int)':
/home/spl211/CLionProjects/Assign1/src/Graph.cpp:24: undefined reference to `Tree::createTree(Session const&, int)'
/home/spl211/CLionProjects/Assign1/src/Graph.cpp:39: undefined reference to `Tree::createTree(Session const&, int)'
这是我的图形 cpp:谁实现了调用 createTree 的 BFS 算法(问题出在哪里)
#include "../include/Graph.h"
#include "../include/Tree.h"
class Tree;
//--constructor--//
Graph::Graph():edges(),size(),neighbours(),infV(){}
Graph::Graph(std::vector<std::vector<int>> matrix) : edges({{}}), size(0), neighbours({}), infV({}) {
edges = matrix;
size = edges.size();
neighbours = matrix;
for (int i = 0; i < edges.size(); i++) {
infV[i] = 0;
}
};
//--getter--//
std::vector<std::vector<int>> Graph::getEdg()const{
return edges;
};
// --function--//
int Graph::BFS(Session &session, int node) {
Tree *BfsTree = Tree::createTree(session, node);
//--build bfs--//
std::queue<Tree *> que;
std::vector<bool> visited;
for (int i = 0; i < size; i++) {
visited.push_back(false);
}
que.push(BfsTree);
visited[node] = true;
while (!que.empty()) {
Tree *curr_root = que.front();
int nodeId = curr_root->getNode();
que.pop();
for (int j = 0; j < edges[nodeId].size(); j++) {
if (edges[nodeId][j] == 1 && !visited[j]) { //if they are neighbours
Tree *child = Tree::createTree(session, j); //create new child
curr_root->addChild(child); //add the child to the tree
que.push(child); //add the child to que
visited[j] = true; //mark him as visited
}
}
}
//--end of bfs--//
//--now we have shortest path tree for our sick node--//
int output = BfsTree->traceTree();
delete (BfsTree);
return output;
}
void Graph::infectNode(int nodeInd) {
infV[nodeInd] = 1;
};
bool Graph::isInfected(int nodeInd) {
return infV[nodeInd] == 1;
};
这是我的 Tree cpp,它实现了 createTree:
#include "../include/Tree.h"
#include "../include/Session.h"
#include <vector>
//--constructor--//
Tree::Tree():node(0),children(){};
Tree::Tree(int rootLabel):node(0),children({}){
node = rootLabel;
}
//--destructor--//
Tree::~Tree(){
for(Tree* tree:children){
delete(tree);
tree= nullptr;
}
};
//----------------RULE OF 5------------------//
//--copy constructor--//
Tree::Tree(const Tree &other):node(0),children(){
node = other.getNode();
for(Tree* child:other.children){
Tree* clone = child->clone();
children.push_back(clone);
}
}
//--copy assignment operator--//
const Tree& Tree::operator=(const Tree& other){
if(this==&other){return *this;}
for(Tree* child:children){
delete (child);
}
for(Tree* child:other.children){
Tree* clone = child->clone();
children.push_back(clone);
}
node = other.getNode();
}
//--move constructor--//
Tree::Tree(Tree&& other){
node = other.getNode();
for(Tree* tree:other.children){
addChild(tree);
tree= nullptr;
}
}
//--move assignment operator--//
const Tree& Tree::operator=(Tree& other){
if(this==&other){return *this;}
node = other.getNode();
for(Tree* child:children){
delete (child);
}
for(Tree* tree:other.children){
addChild(tree);
tree= nullptr;
}
}
//----------------------------------------//
//---FUNCTIONS---//
//--getters--//
int Tree::getNode()const{
return this->node;
}
std::vector<Tree*> Tree::getChildren(){
return children;
};
//--setters--//
void Tree::setNode(int node){
this->node = node;
};
//-add children--//
void Tree::addChild(const Tree& child){
Tree* clone = child.clone();
children.push_back(clone);
};
void Tree::addChild(Tree* child){
children.push_back(child);
};
//--create tree--//
static Tree* createTree(const Session& session, int rootLabel){
if(session.getTreeType()==Cycle){
return new CycleTree(rootLabel,session.getCycle());
}
if(session.getTreeType()==MaxRank){
return new MaxRankTree(rootLabel);
}
if(session.getTreeType()==Root){
return new RootTree(rootLabel);
}
};
//--max function--//
void Tree::maxChild(Tree* tree,int *max,int *node){
if(this->getChildren().size()>*max){
*(max) = getChildren().size();
*(node)=this->getNode();
}
if(tree->getChildren().size()>0){
for(Tree* child:this->getChildren()){
maxChild(child,max,node);
}
}
}
//------------inherent------------//
//--cycle--//
CycleTree::CycleTree(int rootLabel, int currCycle):Tree(rootLabel),currCycle(currCycle){} ;
int CycleTree::traceTree(){
int curr_node = this->getNode();
Tree* curr_tree =this;
int cycleCount=currCycle;
while(cycleCount>=0&&curr_tree->getChildren().size()>0){
curr_tree = curr_tree->getChildren()[0];
curr_node = curr_tree->getNode();
cycleCount--;
}
return curr_node;
};
Tree* CycleTree::clone()const{return new CycleTree(*this);};
//--max--//
MaxRankTree::MaxRankTree(int rootLabel):Tree(rootLabel){};
int MaxRankTree::traceTree(){
int index =this->getNode();
int* node = &index;
int _max = this->getChildren().size();
int *max = &_max;
for(Tree* child:this->getChildren()){
maxChild(child,max,node);
}
return *node;
};
Tree* MaxRankTree::clone()const{return new MaxRankTree(*this);};
//--root--//
RootTree::RootTree(int rootLabel):Tree(rootLabel){};
int RootTree::traceTree(){return this->getNode();};
Tree* RootTree::clone()const{return new RootTree(*this);};
这是我的 make 文件:
# define some Makefile variables for the compiler flags
# to use Makefile variables later in the Makefile: $()
CC = g++
CFLAGS = -g -Wall -Weffc++ -std=c++11
# All Targets
all:Assign1
# Tool invocations
#Executable
Assign1:bin/main.o bin/Agent.o bin/Graph.o bin/Session.o bin/Tree.o
@echo 'Building target: Assign1'
@echo 'Invoking: C++ Linker'
$(CC) -o bin/main bin/Agent.o bin/Graph.o bin/Session.o bin/Tree.o
@echo 'Finished building target: Assign1'
@echo ' '
#Depends on the source and header files
bin/main.o: src/main.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/main.o src/main.cpp
#Depends on the source and header files
bin/Agent.o: src/Agent.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Agent.o src/Agent.cpp
#Depends on the source and header files
bin/Graph.o: src/Graph.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Graph.o src/Graph.cpp
#Depends on the source and header files
bin/Session.o: src/Session.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Session.o src/Session.cpp
#Depends on the source and header files
bin/Tree.o: src/Tree.cpp
$(CC) $(CFLAGS) -c -Iinclude -o bin/Tree.o src/Tree.cpp
#CLean the build directory
clean:
rm -f bin/*
我明白了,你的方法:
static Tree* createTree(const Session& session, int rootLabel){
在您的 cpp 文件中是静态的。因此它在其他文件中是不可见的。
您可能打算创建以下方法:
Tree* Tree::createTree(const Session& session, int rootLabel){
同一个正文,但签名应该是第二个
您将 createTree
定义为:
static Tree* createTree(...)
这定义了一个 non-成员函数,内部链接对其他翻译单元不可见。
如果它应该是静态 member 函数,则将其定义为成员函数(但没有 static
关键字):
Tree* Tree::createTree(...)