C++ Multiple definition of helper function - c++

EDIT: Answered -- the issue was that because the functions had the same signature, despite them being in separate files, C++ saw both versions and got confused.
I have three classes: Table and Bed both inherit from Furniture.
Table and Bed each have a helper function GetLowerCase(std::string) defined in each class individually. When make is run (Makefile shown below), I get an error saying that GetLowerCase in Bed.cpp was first defined in Table.cpp
Makefile:
main: main.o Furniture.o Table.o Bed.o
g++ main.o Furniture.o Table.o Bed.o -o main
main.o: main.cpp
g++ -c main.cpp
Furniture.o: Furniture.cpp Furniture.h
g++ -c Furniture.cpp
Table.o: Furniture.cpp Table.cpp Table.h
g++ -c Table.cpp
Bed.o: Furniture.cpp Bed.cpp Bed.h
g++ -c Bed.cpp
clean:
rm *.o main
Table.cpp:
#include "Table.h"
#include <iostream>
#include <string>
std::string GetLowerCase(std::string str)
{
std::string out;
for (int i=0; i<str.length(); i++)
{
out[i] = tolower(str[i]);
}
return out;
}
Table::Table(const std::string n, std::string wt) : Furniture(n)
{
wood_type = GetLowerCase(wt);
if (wood_type != "pine" && wood_type != "oak")
{
std::cerr << "Wood type must be OAK or PINE.";
}
}
void Table::Print()
{
Furniture::Print();
std::cout << "Wood Type: " << wood_type << std::endl;
}
Bed.cpp:
#include "Bed.h"
#include <iostream>
#include <string>
std::string GetLowerCase(std::string str)
{
std::string out;
for (int i=0; i<str.length(); i++)
{
out[i] = tolower(str[i]);
}
return out;
}
Bed::Bed(const std::string n, std::string sz) : Furniture(n)
{
size = GetLowerCase(sz);
if (size != "twin" && size != "full" && size != "queen" && size != "king")
{
std::cerr << "Bed size must be TWIN, FULL, QUEEN, or KING.";
}
}
void Bed::Print()
{
Furniture::Print();
std::cout << "Size: " << size << std::endl;
}
I would have thought that GetLowerCase would be entirely contained within the .cpp file it was defined in and wouldn't be "seen" by any other files.
It's not in any header or source files besides the two listed above. Very confused, and would love some help!

Either declare your function static or wrap it in an anonymous namespace:
namespace {
// duplicated names here.
}

Your options:
Move all your helper functions into a helper class (like CommomUtils) as static member functions. I recommend this way, it's more C++, and you can avoid duplicate code.
Declare your function as static. So its scope would be in file that defines it, rather than global.
Warp your function with namespace.
Defines your function only once, and in file you want to use it, use extern std::string GetLowerCase(std::string str) to declare it, then you can call it.

Related

for_each algorithm causes basic_string::_M_construct null not valid in C++

In the project to learn C++, I have create a software compose of two easy class
(Home and People).
People have for constructor :
// CONSTRUCTOR
People(): name("NoName"), first_name("NoFirstName"), age(0){}
People(std::string n, std::string fn, int a) : name(n), first_name(fn), age(a){}
And Home have :
// CONSTRUCTOR
Home(): adresse("NoName"){}
Home(std::string addr): adresse(addr){}
In my software, a home have a vector of people, where we can add resident or remove a resident.
My error occur when I try to remove a resident in a home or when I try to print a home.
Here the code of "removeResident" :
void Home::removeHabitant(People const &p)
{
this->getHabitant().erase(std::remove(this->getHabitant().begin(), this->getHabitant().end(), p));
}
Here the code of "operator<<" :
std::ostream & operator<<(std::ostream & out, Home const &h)
{
out << h.getAddr() << "\n"; //OK
if(h.getHabitant().size() > 0) // OK
{
try
{
std::for_each(h.getHabitant().begin(), h.getHabitant().end(), [&out](People const pe){
out << pe << "\n";
}); // ERROR
}
catch(People p)
{
std::cout << "Exception à l'element : " << p << std::endl;
}
}
else // OK
{
out << "Aucun habitant !"; // OK
}
return out ; // OK }
Here the output of my software :
clang++ -Wall -std=c++11 -c -o obj/main.o src/main.cpp -I include
clang++ -Wall -std=c++11 -c -o obj/People.o src/People.cpp -I include
clang++ -Wall -std=c++11 -c -o obj/Home.o src/Home.cpp -I include
clang++ -Wall -std=c++11 -o bin/main obj/main.o obj/People.o obj/Home.o
./bin/main
Peoples's destructor
( NoFirstName - NoName - 0 )
10 rue des Brouettes rouge
Peoples's destructor
Peoples's destructor
( Erwan - AUBRY - 21 )
Peoples's destructor
( Roger - DURAND - 20 )
Peoples's destructor
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
makefile:6: recipe for target 'compile' failed
make: *** [compile] Aborted
Here the main file :
#include <Home.hpp>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
People erwan("AUBRY", "Erwan", 21);
People roger("DURAND", "Roger", 20);
People noName;
// vector<People> lsPeople;
// lsPeople.push_back(erwan);
// lsPeople.push_back(roger);
// copy(lsPeople.begin(), lsPeople.end(), ostream_iterator<People>(cout, "|"));
Home home1("10 rue des Brouettes rouge");
home1.addHabitant(erwan);
home1.addHabitant(roger);
cout << noName << endl;
cout << home1 << endl;
// cout << home1[0] << endl;
// home1.removeHabitant(roger);
// cout << home1[0] << endl;
return 0;
}
After several research I think it's the cause of the home class, so here is the code of home .hpp :
#ifndef HOME_INCLUDED
#define HOME_INCLUDED
#include <People.hpp>
#include <vector>
class Home
{
private:
std::string adresse;
std::vector<People> habitant;
public:
// CONSTRUCTOR
Home(): adresse("NoName"){}
Home(std::string addr): adresse(addr){}
// DESTRUCTOR
~Home(){std::cout << "Home's destructor" << std::endl;}
// GETTER
std::string getAddr() const{return this->adresse;}
std::vector<People> getHabitant() const{return this->habitant;}
// SETTER
void setAddr(std::string const val){this->adresse = val;}
void addHabitant(People const &p){this->habitant.push_back(p);}
void removeHabitant(People const &p);
// OPERATOR
People & operator[](unsigned int const val){return this->habitant[val];}
};
std::ostream & operator<<(std::ostream & out, Home const &h);
#endif
I hope you have any idea for my problems.
PS: sorry for my english, and sorry if I have make anything of badness I'm new as help seeker in StackOverflow
As also seem by molbdnilo in a remark, in std::ostream & operator<<(std::ostream & out, Home const &h) you do the iteration
std::for_each(h.getHabitant().begin(), h.getHabitant().end(), [&out](People const pe){
that supposes h.getHabitant().begin() and h.getHabitant().end() are iterators on the same vector but
std::vector<People> getHabitant() const{return this->habitant;}
returns each time a new copy of the vector.
If you do not want to modify getHabitant to return a const reference to habitant you have to memorize the vector on which you iterate.
std::vector<People> v = h.getHabitant();
std::for_each(v.begin(), v.end(), [&out](People const pe){
but I encourage you to modify getHabitant() to be
const std::vector<People> & getHabitant() const {return this->habitant;}

Exclude C++ standard library function calls from gprof output

I am using the C++ standard library in some C++ code and this makefile:
CC=g++
CXXFLAGS=-Wall -Werror -ggdb3 -std=c++11 -pedantic $(OTHERFLAGS)
cpp_sort: cpp_sort.o
g++ -o $# $(CXXFLAGS) $^
clean:
rm -rf *.o cpp_sort *~
The source code:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void get_input(vector<int>& items, int size) {
for (int i = 0; i < size; ++i) {
int element;
cin >> element;
items.push_back(element);
}
}
void cpp_sort(vector<int>& items) {
sort(items.begin(), items.end());
}
void print_array(vector<int>& items) {
for (auto& item : items) {
cout << item << ' ';
}
cout << endl;
}
int main() {
int size;
cin >> size;
vector<int> items;
items.reserve(size);
get_input(items, size);
cpp_sort(items);
print_array(items);
}
I call make like this:
make OTHERFLAGS=-pg
run the program (where large.txt is a long list of integers):
./cpp_sort <large.txt
and view the profiling information:
grof ./cpp_sort
Which is fine and it does work, but the calling of my functions is obscured by all the C++ standard library function calls. Is there a way to exclude the standard library internal function calls?

Undefined reference to isPrime(int) but it is defined

I am working on a practical assignment which requires us to use an external function to determine whether a integer entered is a prime number. I have created the header file, external functions file and main file but when i compile using
g++ -o main main.cpp extFunc.cpp
but I get the error:
/tmp/cca073oR.o: In function 'main':
main.cpp:(.text+0x42): undefined reference to 'isPrime(int)'
collect2: error: ld returned 1 exit status
The following are my cpp and header classes:
1)extFunc.h
bool isPrime(int num);
2)extFunc.cpp
# include "extFunc.h"
bool isPrime(int num) {
int i;
bool numPrime;
//Determine if number is prime
if (num <= 0) {
numPrime = false;
}
if (num = 1) {
numPrime = false;
}
if (num = 2) {
numPrime = true;
}
if (num = 3) {
numPrime = true;
}
else {
numPrime = true;
for(i = 2; i < num; i++) {
if ((num%i) == 0){
numPrime = false;
break;
}
}
}
//Return values
if (numPrime == true) {
return true;
} else {
return false;
}
}
3) main.cpp
#include <iostream>
#include "extFunc.h"
using namespace std;
int main() {
//Variables
int uNum;
bool prime;
cout << "Enter a number: ";
cin >> uNum;
prime = isPrime(uNum);
if (prime = true) {
cout << uNum << " is prime" << endl;
}
else {
cout << uNum << " is not prime" << endl;
}
return 0;
}
I have tried some of the other suggestions I was able to find on the site including using #ifndef in the header file but it did not fixed anything for me. I am unable to identify what possible could be the problem since the function in the header file and the function file is the same and it is called correctly (from what I can see) in the main file.
Thanks for all the responses. I managed to fix the issue. The university posted a guide to help us with the assignment this morning and I changed my makefile which fixed the issue.
This is what I had for my makefile
main: main.o extFunc.o
g++ -o main main.o extFunc.o
main.o: main.cpp extFunc.h
g++ -c main.cpp
extFunc.o: extFunc.h extFunc.cpp
g++ -c extFunc.cpp
run:
./main
clean:
rm *. main
I think you confuse between "=" and "=="
for instance
if (num = 1) {
[...]
}
should be :
if (num == 1) {
[...]
}
Perhapse that the use of "const" keyword is a good deal in order to avoid this kind of mistakes.
The error occurs :
on line 10, 13 and 16 in extFunc.cpp
and line 16 in main.cpp

Getting a Dwarf Error Version '4'

I am having some trouble with my school project. I think that it may be an error with my use of pointers but I am not sure why I am getting this error. This code is incomplete but I am trying to test it along the way. Do you have any idea why I am getting this error and what does it mean? Thanks!
Error from Cygwin Terminal
-bash-3.2$ make clean
rm -rf *.o simulate
-bash-3.2$ make simulate
g++ -c -g Main.cpp
g++ -c -g Maze.cpp
g++ Main.o Maze.o -o simulate
/usr/bin/ld: Dwarf Error: found dwarf version '4', this reader only handles version 2 information.
Maze.o: In function `Maze::createMaze(char*)':
Maze.cpp:(.text+0x49): undefined reference to `Node::Node(char)'
collect2: error: ld returned 1 exit status
make: *** [simulate] Error 1
Main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "Maze.h"
using namespace std;
int main()
{
int array_size = 1024;
char * mazeArray = new char[array_size];
int position = 0;
string mazeName;
Maze Maze1;
cout << "Enter the name of the maze file: ";
getline(cin, mazeName);
ifstream fin(mazeName.c_str());
//File opened successfully
if(fin.is_open())
{
while(!fin.eof() && position < array_size)
{
fin.get(mazeArray[position]); //reading one character from file to mazeArray
position++;
}
mazeArray[position-1] = '\0'; //placing character mazeArray terminating character
for(int i = 0; mazeArray[i] != '\0'; i++){
if(isspace(mazeArray[i]))
mazeArray[i] = mazeArray[i+1];
}
cout << "Displaying mazeArray..." << endl << endl;
//this loop display all the charaters in mazeArray till \0
for(int i = 0; mazeArray[i] != '\0'; i++)
{
cout << mazeArray[i];
}
cout << endl;
Maze1.createMaze(mazeArray);
}
else //file could not be opened
{
cout << "File could not be opened." << endl;
}
return 0;
}
Maze.h
#ifndef MAZE_H
#define MAZE_H
#include <string>
#include <sstream>
#include <vector>
#include "Node.h"
using namespace std;
class Maze
{
public:
void createMaze(char*);
void availablePaths();
void displayPath();
void moveNorth();
void moveSouth();
void moveEast();
void moveWest();
int getroomCount();
char getpathHistory();
char getcurrentRoom();
private:
int roomCount;
char pathHistory[];
Node* currentRoom;
Node* nodeArray[12];
struct isPath;
vector<Node*> nodeVector;
};
#endif
Maze.cpp
#include <iostream>
#include <string>
#include "Maze.h"
using namespace std;
Node* Node1;
void Maze::createMaze(char *inFile){
int count = 0;
//Creates Nodes for Maze
for(int ii = 0; ii <= 12; ii++){
Node1 = new Node(inFile[count]);
nodeVector.push_back(Node1);
count = count + 5;
//If there is not another node break out of the for loop.
if(inFile[count] == '\0'){
break;
}
}
}
void Maze::availablePaths(){
}
void Maze::displayPath(){
}
void Maze::moveNorth(){
}
void Maze::moveSouth(){
}
void Maze::moveEast(){
}
void Maze::moveWest(){
}
int Maze::getroomCount(){
}
char Maze::getpathHistory(){
}
char Maze::getcurrentRoom(){
}
Node.h
#ifndef NODE_H
#define NODE_H
#include <string>
#include <map>
#include <sstream>
using namespace std;
class Node
{
public:
Node(char);
void setNodeName(char);
void attachNewNode(Node, int);
Node *getAttachedNode(int);
private:
char name; // Title that is displayed above the menu.
Node *attachedNodes[4];
};
#endif
Node.cpp
#include <iostream>
#include <string>
#include <vector>
#include "Node.h"
using namespace std;
Node::Node(char name) : name(name) {
}
void Node::setNodeName(char tempName){
name = tempName;
}
void Node::attachNewNode(Node temp, int direction){
attachedNodes[direction] = temp;
}
Node Node::getAttachedNode(int direction){
return attachedNodes[direction];
}
makefile
#!/bin/bash
#file:makefile
CC = g++
CFLAGS = -c -g
simulate: Main.o Maze.o
$(CC) Main.o Maze.o -o simulate
Main.o: Main.cpp Maze.h
$(CC) $(CFLAGS) Main.cpp
Maze.o: Maze.cpp Menu.h Node.h
$(CC) $(CFLAGS) Maze.cpp
Node.o: Node.cpp Node.h
$(CC) $(CFLAGS) Node.cpp
clean:
rm -rf *.o simulate
The problem is not in your code, per se.
One problem is that your linking command is failing because you are not linking all your object files. You need to link Main.o, Maze.o and Node.o to create the executable:
g++ Main.o Maze.o Node.o -o simulate
Another problem is that your compiler is newer than your linker. The compiler is generating debugging information using Dwarf version 4, but your linker (/usr/bin/ld) only understands Dwarf version 2.
/usr/bin/ld: Dwarf Error: found dwarf version '4', this reader only handles
version 2 information.
You need to update your linker to a newer version compatible with the compiler you are using.
Or, as janneb suggests in a comment, you can use -gdwarf-2 in both the compilation and link lines. In the makefile:
CFLAGS = -c -gdwarf-2
FILES.cpp = Main.cpp Maze.cpp Node.cpp
FILES.o = $(FILES.cpp:.cpp=.o}
simulate: $(FILES.o)
$(CC) $(CFLAGS) $(FILES.o) -o $#
(There should be few parts of command lines in a makefile that are not macro invocations; then you can change everything more easily.)
You will need to remove the Dwarf-4 object files and recompile to avoid the error/warning.
You can simply fix this by:
export CFLAGS='-gdwarf-2 -gstrict-dwarf'
Then, remake your project.

Undefined reference errors c++

I'm having trouble linking my program. All the classes compile fine with
g++ -c main.cpp
g++ -c Server.cpp
g++ -c Client.cpp
But when I go to link them
g++ main.o Server.o Client.o -o main.out -lsfml-network -lsfml-system
I'm getting undefined references for the functions in my Client and Server classes.
main.cpp:(.text+0x1ba): undefined reference to `(anonymous namespace)::Server::Server()'
main.cpp:(.text+0x1c6): undefined reference to `(anonymous namespace)::Server::getMessage()'
main.cpp:(.text+0x210): undefined reference to `(anonymous namespace)::Server::~Server()'
main.cpp:(.text+0x227): undefined reference to `(anonymous namespace)::Client::Client()'
main.cpp:(.text+0x23d): undefined reference to `(anonymous namespace)::Client::sendMessage(std::string const&)'
main.cpp:(.text+0x287): undefined reference to `(anonymous namespace)::Client::~Client()'
main.cpp:(.text+0x3e9): undefined reference to `(anonymous namespace)::Server::~Server()'
main.cpp:(.text+0x407): undefined reference to `(anonymous namespace)::Client::~Client()'
collect2: error: ld returned 1 exit status
Any help is much appreciated.
main.cpp
#include <iostream>
#include <cstdio>
#include <string>
#include "include/Server.hpp"
#include "include/Client.hpp"
void printOptions(std::string const* const, size_t const&);
char const getInput(std::string const* options, size_t const& size);
int main()
{
const std::string YES_NO[] = {
"Yes",
"No"
};
const std::string OPTIONS[] = {
"Server",
"Client"
};
const std::string CONTINUE = "Continue?\n\n";
const std::string PROMPT = "Run as?\n";
const std::string RECIPEINT = "127.0.0.1";
const size_t SIZE = sizeof(OPTIONS) / sizeof(std::string);
std::cout << PROMPT;
const char INPUT = getInput(OPTIONS, SIZE);
char response;
// Server
if (INPUT == '1')
{
Server server;
do
{
server.getMessage();
std::cout << CONTINUE;
response = getInput(YES_NO, 2);
} while (response == '1');
}
// Client
else if (INPUT == '2')
{
Client client;
do
{
client.sendMessage(RECIPEINT);
std::cout << CONTINUE;
response = getInput(YES_NO, 2);
} while (response == '1');
}
// else serious problem
}
/* Function used to display a list of options to the user.
Each option is displayed on a new line preceeded with
its input number and provided option text.
Ex:
options[] = {"Option A", "Option B"}
Will print:
1) Option A
2) Option B
#param options
An array of std::string that will be displayed
as the list of options.
#param size
The number of different options the options array contains.
*/
void printOptions(std::string const* options, size_t const& size)
{
for (size_t i = 0; i < size; i++)
{
std::cout << i + 1 << ") ";
std::cout << options[i] << std::endl;
}
}
/* Used to return a users choice from a list of options.
*WARNING*
Providing an array with more than 9 options will give
unexpected return values.
If it is necesszary to provide a user with mroe than 9 options
have the 9th option be "More options..." from which you may call
getInput() again, with additonal options.
#param options
An array of std::string that will be displayed
for the users choice.
#param size
The number of different optins the optinos array contains.
#return const char
A number from 1 to 9 representing the users choice from
the options array.
1 = array index 0, 9 = array index 8.
*/
const char getInput(std::string const* options, size_t const& size)
{
printOptions(options, size);
char input;
bool needInput = true;
while (needInput)
{
std::cout << "Enter a number: ";
std::cin >> input;
for (size_t i = 0; i < size; i++)
{
char optionBuffer[2];
std::sprintf(optionBuffer, "%zu", i + 1);
if (input == *optionBuffer)
{
needInput = false;
break;
}
}
if (needInput)
std::cout << "Option not available." << std::endl;
}
return input;
}
Server.hpp
#pragma once
#include <SFML/Network.hpp>
#include <iostream>
#include <string>
namespace
{
class Server
{
public:
Server();
~Server();
static const unsigned short SERVER_PORT = 54000;
void getMessage();
protected:
private:
sf::UdpSocket socket;
};
};
Server.cpp
#include "include/Server.hpp"
//using namespace;
Server::Server()
{
this->socket.bind(SERVER_PORT);
}
Server::~Server() {}
// TODO: Ensure that the socket is bound to a port.
void Server::getMessage()
{
sf::IpAddress sendersAddress;
unsigned short sendersPort;
sf::Packet sendersPacket;
// Failed to recieve packet
if (this->socket.receive(sendersPacket, sendersAddress, sendersPort)
!= sf::Socket::Done
)
{
std::cout << "Failed to recieve packet." << std::endl;
}
// Sucessfully recievd packet
else
{
std::string message;
sendersPacket >> message;
std::cout << "Recieved message:\n\n" << message << std::endl;
}
}
Client.hpp
#pragma once
#include "Server.hpp"
#include <SFML/Network.hpp>
namespace
{
class Client
{
public:
Client();
~Client();
void sendMessage(std::string const&);
protected:
private:
sf::UdpSocket socket;
};
};
Client.cpp
#include "include/Client.hpp"
//using namespace;
Client::Client()
{
this->socket.bind(sf::Socket::AnyPort);
}
Client::~Client()
{
}
void Client::sendMessage(std::string const& recipient)
{
std::string message;
sf::Packet packet;
std::cout << "Write a message:\n" << std::endl;
do
{
std::getline(std::cin, message);
} while (!message.size());
socket.send(packet, recipient, Server::SERVER_PORT);
}
The problem is that your Server and Client class declarations are inside unnamed (or anonymous) namespaces. To fix it, simply give your namespaces a name, such as:
namespace MyNamespace
{
class Server
{
// ...
};
}
In the *.cpp files (including main.cpp), make sure you have a corresponding using directive, such as:
using namespace MyNamespace;
Alternatively, you can fully-qualify the names when you use them, e.g. MyNamespace::Server instead of just Server.
As a side note, unnamed namespaces are actually valid and sometimes very useful. When the compiler sees a namespace without a name, it comes up with a unique internal name for it, and immediately follows it with a hidden using namespace ... directive. That's very useful for things which you want to define and use only within a single *.cpp file, because it can help avoid naming conflicts. (An older way to do something similar involved the static keyword).
As a rule though, don't use unnamed namespaces in a header file.