Is it possible to create String class with String.cpp and String.h in c++ stl project?
String.h
#include <string>
class String {
public:
static std::string Replace(const std::string& str, const std::string& oldValue, const std::string& newValue);
};
There are compilation errors unless the class is renamed to something else like Stringy
Instead of a class with only static members, you use a namespace in C++.
#include <string>
namespace String {
std::string Replace(const std::string& str, const std::string& oldValue, const std::string& newValue);
};
You need to remove the static from the class declaration and your posted code works just fine then.
Related
This question already has an answer here:
What exactly is One Definition Rule in C++?
(1 answer)
Closed 4 years ago.
I am working on a program that simulates a game of GoFish. I have a weird error that is making it difficult to make any progress. I get the following error when building "error: redefinition of 'Player'." I have looked at various websites regarding the error, but it seems as if all of the code includes the cpp in the header and the header in the cpp. However, mine does not.
Here is the .cpp file:
#include "player.h"
Player::Player(){
myName = "";
}
Player::Player(string name) {
myName = name;
}
string Player::getName() const {
return myName;
}
I have excluded the methods which aren't giving errors.
Additionally, here is the .h file:
#ifndef UNTITLED3_PLAYER_H
#define UNTITLED3_PLAYER_H
#include <iostream>
#include <string>
#include <vector>
#include "card.h"
using namespace std;
class Player
{
public:
Player();
Player(string name) {
myName = name;
}
string getName() const {
return myName;
}
void addCard(Card c); //adds a card to the hand
void bookCards(Card c1, Card c2);
bool checkHandForBook(Card &c1, Card &c2);
bool rankInHand(Card c) const;
Card chooseCardFromHand() const;
bool cardInHand(Card c) const;
Card removeCardFromHand(Card c);
string showHand() const;
string showBooks() const;
int getHandSize() const;
int getBookSize() const;
private:
vector <Card> myHand;
vector <Card> myBook;
string myName;
};
#endif
The only two function which are getting redefinition errors are the constructor and getName. What could be causing this?
You've included the entire constructor and getName() function in the header and in the .cpp file. They should only exist in one or the other.
I'm having an issue compiling my C++ file.
This is the error I get:
Multiple markers at this line
- Member declaration not found
- definition of implicitly-declared 'InsultGenerator::InsultGenerator(const InsultGenerator&)'
I'm using MinGW as my compiler.
Here is the C++ code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "Insultgenerator_0hl14.h"
using namespace std;
FileException::FileException(const string& m) : message(m){}
string& FileException::what(){ return message;}
NumInsultsOutOfBounds::NumInsultsOutOfBounds(const string& m) : message(m){}
string& NumInsultsOutOfBounds::what(){ return message;}
InsultGenerator::InsultGenerator(const InsultGenerator& ) {}
void InsultGenerator::initialize() const{
int cols(0);
string x;
string filename("InsultsSource.txt");
ifstream file(filename.c_str());
if(file.fail()){
throw FileException("File not read.");
}
while(file >> x){
}}
//vector<string> InsultGenerator::talkToMe() const{
// };//end talkToMe
// vector<string> InsultGenerator::generate(const int n) const{
// };//end generate
//int InsultGenerator::generateAndSave(const string filename, const int n) const{
//};//end generateAndSave
Here is the header file:
#ifndef INSULTGENERATOR_0HL14_H_
#define INSULTGENERATOR_0HL14_H_
#include <string>
#include <vector>
using namespace std;
class InsultGenerator{
public:
InsultGenerator(vector<string>);
void initialize() const;
string talkToMe() const;
vector<string> generate(const int) const;
int generateAndSave (const string, const int) const;
private:
vector<string> colA;
vector<string> colB;
vector<string> colC;
};
class FileException{
public:
FileException(const string&);
string& what();
private:
string message;
};
class NumInsultsOutOfBounds{
public:
NumInsultsOutOfBounds(const string &);
string& what();
private:
string message;
};
#endif
You are implementing InsultGenerator's copy-constructor although you haven't declared it.
Add InsultGenerator(const InsultGenerator& ); to your InsultGenerator class.
Like so:
class InsultGenerator
{
public:
InsultGenerator(vector<string>); // also better remove that one since I don't
// think you have implemented it
InsultGenerator(const InsultGenerator &); // here
void initialize() const;
string talkToMe() const;
vector<string> generate(const int) const;
int generateAndSave (const string, const int) const;
private:
vector<string> colA;
vector<string> colB;
vector<string> colC;
};
Edit:
class InsultGenerator
{
public:
InsultGenerator(vector<string>); // Remove this line.
InsultGenerator(const InsultGenerator &); // Add this line.
void initialize() const;
string talkToMe() const;
......
}
I have the following code which implements a simple Hash/Dict in C++
Hash.h
using namespace std;
#include <string>
#include <vector>
class Hash
{
private:
vector<const char*> key_vector;
vector<const char*> value_vector;
public:
void set_attribute(const char*, const char*);
string get_attribute(const char*);
};
Hash.cpp
using namespace std;
#include "Hash.h"
void Hash::set_attribute(const char* key, const char* value)
{
key_vector.push_back(key);
value_vector.push_back(value);
}
string Hash::get_attribute(const char* key)
{
for (int i = 0; i < key_vector.size(); i++)
{
if (key_vector[i] == key)
{
return value_vector[i];
}
}
}
At the moment, the only type it can take as a key/value is a const char*, but I want to extend it so that it can take any type (obviously only one type per hash). I was thinking about doing that by defining a constructor which takes a type as an argument, but I don't know at all how to do that in this situation. How would I do that, and how would I implement it so set_attribute is defined to take that type?
Compiler: Mono
You need to use templates to do this. Here is an example.
#ifndef HASH_INCLUDED_H
#define HASH_INCLUDED_H
#include <string>
#include <vector>
template <typename T>
class Hash
{
private:
std::vector<const T*> key_vector;
std::vector<const T*> value_vector;
public:
void set_attribute(const T*, const T*)
{
/* you need to add definition in your header file for templates */
}
T* get_attribute(const T*)
{
/* you need to add definition in your header file for templates */
}
};
#endif
Please note that I have removed using namespace std; as it completely removes the entire point of having namespaces, especially in header files.
Edit: Also, is there any reason why you are not using std::vector's iterator to loop through its items ?
Why gcc cannot compile successful of the codes below?
Can the constructor be defined out of the class?
#include <string>
using std::string;
class Person{
public:
Person(const string &a, const string &b);
private:
string name, address;
};
Person::Person(const string &a, const string &b){
name(a);
address(b);
}
Thanks!
Because neither name nor address are callable. You probably meant to put them into a member-initializer-list.
Person::Person(const string &a, const string &b)
: name(a), address(b)
{
}
Your syntax is wrong:
Person::Person(const string &a, const string &b) : name(a), address(b) {}
You just wrote it wrong. It should be:
Person::Person(const string &a, const string &b) : name(a), address(b) { }
In principle, and very much in practice, too, you can and should define member functions outside the class definition to decouple the code base and reduce compile times.
This is called separation of implementation and declaration. It is actually a good idea to keep your implementations separately, in a cc or cpp file.
Thus, in your header:
//Person.h
#ifndef PERSON_H // <---- include header guards in your headers
#define PERSON_H
#include <string>
//using std::string; <--- you should remove this line, you don't want to import namespaces
// in your header file, or else they are imported in all
// files including this header
class Person{
public:
Person(const std::string &a, const std::string &b);
private:
std::string name, address; // qualify your names in the header
};
#endif
and your implementation file:
//Person.cpp
#include "Person.h"
using namespace std; // <---- if you wish, import the std namespace in your global namespace
// in the implementation file
Person::Person(const string &a, const string &b):
name(a), // <---- correct syntax of initializer lists
address(b)
{
}
I'm pretty sure I've included the qanda class, but when I try to declare a vector that contains it or a class of that type I get an error saying that qanda is undefined. Any idea what the problem might be?
bot_manager_item.h
#pragma once
#include "../bot_packet/bot_packet.h"
#include <vector>
class bot_manager_item;
#include "qanda.h"
#include "bot_manager.h"
class bot_manager_item
{
public:
bot_manager_item(bot_manager* mngr, const char* name, const char* work_dir);
~bot_manager_item();
bool startup();
void cleanup();
void on_push_event(bot_exchange_format f);
bool disable;
private:
void apply_changes();
bot_manager *_mngr;
std::string _name;
std::string _work_dir;
std::string _message;
std::string _message_copy;
std::vector<qanda> games;
qanda test;
char _config_full_path[2600];
};
qanda.h
#ifndef Q_AND_A
#define Q_AND_A
#include "users.h"
#include "..\bot_packet\bot_packet.h"
#include "bot_manager.h"
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <fstream>
class qanda
{
public:
qanda(bot_manager * manager, std::string name, std::string directory);
~qanda(){};
void room_message(std::string username, std::string user_message);
void timer_tick();
private:
// data members
std::string question;
std::string answer;
std::string directory;
std::string command_prefix;
std::string name;
Users users;
std::map <std::string, std::string> questions_and_answers;
int time_per_question; // seconds
int time_between_questions; // seconds
int timer; // milliseconds
bool is_delayed;
bool is_playing;
bot_manager * manager;
// functions
void new_question();
void send_message(std::string msg);
void announce_question();
void load_questions();
};
#endif
Solved: I ended up refactoring the code in such a way as to avoid the use of bot_manager within the qanda class.
I suspect a circular #include problem. Is it possible qanda.h indirectly includes bot_manager_item.h?
It looks like you may be able to reduce header dependencies by using a forward declaration
class bot_manager;
instead of #include "bot_manager.h" in one or both of your posted header files.