I've read a lot of questions regarding this matter, but none of them seem to solve my issue. Code below:
Logger.cpp
#include "Includes.h"
namespace DemoProject {
class Logger {
public:
static void Logger::printm(CEGUI::String Message) {
std::cout << currentDateTime() << " >> " << Message << std::endl;
}
private:
static const std::string currentDateTime() {
time_t now = time(0);
struct tm tstruct;
char buf[80];
tstruct = *localtime(&now);
strftime(buf, sizeof(buf), "%d-%m-%Y %X", &tstruct);
return buf;
}
};
}
logger.h
#ifndef LOGGER_H
#define LOGGER_H
#pragma once
#include "Includes.h"
namespace DemoProject {
class Logger {
public:
static void Logger::printm(CEGUI::String Message);
};
}
#endif
Includes.h
#ifndef INCLUDES_H
#define INCLUDES_H
#include <iostream>
#include <string>
#include <stdio.h>
#include <time.h>
#include <CEGUI/CEGUI.h>
#include <CEGUI/RendererModules/OpenGL/GLRenderer.h>
#include <SDL.h>
#include <SDL_opengl.h>
#include "Logger.h"
#endif
Sorry for bad formating of the post, but that's the best I could do. I am mostly a C# developer, but I am trying to learn C++ through doing different exercises I create on my own. From a C# developers view, this code is okay, but I don't know, I'm still a beginner.
There are a couple of things you're doing weird. But the most important is you don't need to declare the class again in the .cpp file. You just implement the functions:
namespace DemoProject {
void Logger::printm(CEGUI::String Message) {
std::cout << currentDateTime() << " >> " << Message << std::endl;
}
static const std::string currentDateTime() {
...
}
}
You also didn't declare currentDateTime in the header, so that won't compile right. You also don't need to scope the class in the declaration since you're already in the class, so your header should look like:
namespace DemoProject {
class Logger {
public:
static void printm(CEGUI::String Message);
static const std::string currentDateTime();
};
}
Related
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 7 years ago.
Please see my previous post here:
Undefined type error even with forward declaration
I moved the definitions to cpp files and I still face the issue. Any ideas why? My files look like this:
Header1.hpp
#ifndef HEADER1_HPP
#define HEADER1_HPP
namespace sample_ns
{
class sample_class{
public:
static int getNumber();
static void print();
};
}
#endif
Header2.hpp
#ifndef HEADER2_HPP
#define HEADER2_HPP
namespace sample_ns
{
class sample_class2{
public:
sample_class2();
int getNumber2();
};
}
#endif
Source1.cpp
#include "Header1.hpp"
#include "Header2.hpp"
#include "stdafx.h"
#include <iostream>
namespace sample_ns
{
int sample_class::getNumber()
{
sample_class2 obj;
return obj.getNumber2();
}
void sample_class::print()
{
std::cout << "Print utility function" << std::endl;
}
}
Source2.cpp
#include "Header2.hpp"
#include "Header1.hpp"
#include "stdafx.h"
#include <iostream>
namespace sample_ns
{
sample_class2::sample_class2()
{
sample_class::print();
}
int sample_class2::getNumber2()
{
sample_class::print();
return 5;
}
}
In my main I call it as:
std::cout << sample_ns::sample_class::getNumber() << std::endl;
I get 'sample_class2' : undeclared identifier. I tried adding class sample_class2; but that still gives me error
EDIT:
my main file:
#include "stdafx.h"
#include <iostream>
#include "Header1.hpp"
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "hello" << std::endl;
std::cout << sample_ns::sample_class::getNumber() << std::endl;
return 0;
}
The best practice for declaring classes and namespaces in header and cpp files is using structure likes below:
Header1.hpp
#ifndef HEADER1_HPP
#define HEADER1_HPP
#include "Header2.hpp"
#include <iostream>
namespace sample_ns
{
class sample_class{
public:
static int getNumber();
static void print();
};
}
#endif
Source1.cpp
#include "Header1.hpp"
namespace sample_ns
{
int sample_class::getNumber()
{
sample_class2 obj;
return obj.getNumber2();
}
void sample_class::print()
{
std::cout << "Print utility function" << std::endl;
}
}
So by including in header files and using ifndef you become sure that circular dependencies will not occure.
I am attempting to make part of a program that uses a bank account class as the base class and checking and savings as the derived classes. I have been trying to set up the basic framework before I do any fancy data handling and I've followed some tutorials to get a better understanding of classes and inheritance.
I have looked for answers but the answers I have found don't seem to be my problem but I might just need another set of eyes on my code.
the compiler errors:
In function main':
badriver.cpp:20: undefined reference toChecking::getAccount()'
badriver.cpp:23: undefined reference to Checking::setAccount(int)'
badriver.cpp:24: undefined reference toSavings::setAccount(int)'
badriver.cpp:26: undefined reference to `Checking::getAccount()'
badriver.cpp
#include "BankAccount.cpp"
#include "Checking.cpp"
#include "Savings.cpp"
#include <string>
#include <iostream>
using namespace std;
int main(){
Checking c;
Savings s;
cout << "Checking: " << c.getAccount() << " - Type: " << c.getType() << endl;
cout << "Savings: " << s.getAccount() << " - Type: " << s.getType() << endl;
c.setAccount(9);
s.setAccount(15);
cout << "New Checking: " << c.getAccount() << endl;
cout << "New Savings: " << s.getAccount() << endl;
return 0;
}
BankAccount.h
#ifndef BANKACCOUNT_H
#define BANKACCOUNT_H
#include <string>
using std::string;
using std::ostream;
using std::istream;
class BankAccount{
private:
int myAccount;
const char* color;
public:
// default constructor
BankAccount();
BankAccount(int account);
virtual ~BankAccount();
virtual void setAccount(int)=0;
int getAccount();
//
// void setSAccount(int);
// int getSAccount();
//
virtual const char* getColor();
virtual const char* getType() = 0;
//virtual const char* getCType() = 0;
protected:
void setColor(const char*);
};
#endif // BANKACCOUNT_H
BankAccount.cpp
#include "BankAccount.h"
#include "Checking.h"
#include "Savings.h"
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
// default constructor
BankAccount::BankAccount(){
account = 1;
}
BankAccount::~BankAccount(){}
// void BankAccount::setAccount(int account){
// myAccount = account;
// }
int BankAccount::getAccount(){
return myAccount ;
}
BankAccount::BankAccount(int account){
myAccount = account;
}
const char* BankAccount::getColor(){
return color;
}
void BankAccount::setColor(const char* c){
color = c;
}
Checking.h
#ifndef CHECKING_H
#define CHECKING_H
#include "BankAccount.h"
#include <string>
using std::string;
using std::ostream;
using std::istream;
class Checking : public BankAccount{
private:
const char* type;
public:
Checking();
virtual ~Checking();
void setAccount(int account);
virtual const char* getType();
void setChecking(int);
int getChecking();
};
#endif //CHECKING_H
Checking.cpp
#include "Checking.h"
#include <string>
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
Checking::Checking() : BankAccount(1), type("Checking"){}
Checking::~Checking(){}
BankAccount::~BankAccount(){}
void BankAccount::setAccount(int account){
myAccount = account;
}
const char* Checking::getType(){
return type;
}
Savings.h
#ifndef SAVINGS_H
#define SAVINGS_H
#include "BankAccount.h"
#include <string>
using std::string;
using std::ostream;
using std::istream;
class Savings: public BankAccount{
private:
const char* type;
public:
Savings();
virtual ~Savings();
void setAccount(int account);
virtual const char* getType();
void setSavings(int);
int getSavings();
};
#endif // SAVINGS_H
Savings.cpp
#include "Savings.h"
#include <string>
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
Savings::Savings() : BankAccount(2), type("Savings"){}
Savings::~Savings(){}
BankAccount::~BankAccount(){}
void BankAccount::setAccount(int account){
myAccount = account;
}
const char* Savings::getType(){
return type;
}
Thanks for any help pointing me in the right direction.
Checking.cpp and Savings.cpp contain:
BankAccount::~BankAccount(){}
void BankAccount::setAccount(int account){
myAccount = account;
}
This causes undefined behaviour because you defined those functions in multiple files. You need to delete those lines from Checking.cpp and Savings.cpp, and instead put in definitions for the functions which are listed as being missing in the compiler output:
void Checking::setAccount(int account){
// code here
}
etc.
Here are my code files:
main.cpp
#include <iostream>
#include <fstream>
#include "Car.h"
#include "Engine.h"
using namespace std;
int main() {
Car* car = new Car(1984);
/* do something here */
delete car;
return 0;
}
Car.h
#ifndef CAR_H
#define CAR_H
#include <iostream>
using namespace std;
#include "Engine.h"
class Car {
public:
Car(int);
virtual ~Car();
void serialize(ostream& s) {
engine.serialize(s);
s << ' ' << yearModel;
}
void unserialize(istream& s) {
engine.unserialize(s);
s >> yearModel;
}
private:
Engine engine;
int yearModel;
};
#endif /* CAR_H */
Car.cpp
#include "Car.h"
Car::Car(int year) {
yearModel = year;
}
Car::~Car() {
}
Engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <iostream>
using namespace std;
class Engine {
public:
Engine();
virtual ~Engine();
void serialize(ostream& s) {
s << ' ' << engineType;
}
void unserialize(istream& s) {
s >> engineType;
}
private:
int engineType;
};
#endif /* ENGINE_H */
Engine.cpp
#include "Engine.h"
Engine::Engine() {
engineType = 1;
}
Engine::~Engine() {
}
What I want to do in the main.cpp is to save the created Car object to file.txt and later read it from there. How does that exactly work? For example: how do I call the serialization function in Car class?
I'm sorry if I sound like a noob, but this whole serialization thing is pretty new to me.
Edit: Code compiles now when I added 'void' in front of all serialize- and unserialize-functions.
This has nothing to do with serialization: a function needs a return type, even if it is void. So this is wrong:
serialize(ostream& s) // look, no return type.
You probably need to either return void,
void serialize(ostream& s) { /* code as before */ }
or return the stream by reference to allow for chaining:
ostream& serialize(ostream& s) {
return s << ' ' << engineType;
}
I've got a third party library named person.lib and its header person.h. This is my actual project structure and it compiles and runs perfectly.
Actual Structure:
main.cpp
#include <iostream>
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"
using namespace person;
using namespace std;
class Client : public Person
{
public:
Client();
void onMessage(const char * const);
private:
void gen_random(char*, const int);
};
Client::Client() {
char str[11];
gen_random(str, 10);
this->setName(str);
}
void Client::onMessage(const char * const message) throw(Exception &)
{
cout << message << endl;
}
void Client::gen_random(char *s, const int len) {
//THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}
int main()
{
try
{
Person *p = new Client;
p->sayHello();
}
catch(Exception &e)
{
cout << e.what() << endl;
return 1;
}
return 0;
}
I want to refactor my code by dividing the declaration of my Client class from its definition and create client.h and client.cpp. PAY ATTENTION: sayHello() and onMessage(const * char const) are functions of the person library.
Refactored Structure:
main.cpp
#include <iostream>
#include "client.h"
using namespace person;
using namespace std;
int main()
{
try
{
Person *p = new Client;
p->sayHello();
}
catch(Exception &e)
{
cout << e.what() << endl;
return 1;
}
return 0;
}
client.cpp
#include "client.h"
using namespace person;
using namespace std;
Client::Client() {
char str[11];
gen_random(str, 10);
this->setName(str);
}
void Client::onMessage(const char * const message) throw(Exception &)
{
cout << message << endl;
}
void Client::gen_random(char *s, const int len) {
//THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}
client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"
class Client : public Person
{
public:
Client();
void onMessage(const char * const);
private:
void gen_random(char*, const int);
};
#endif
As you can see, I've simply created a client.h in which there's the inclusion of the base class person.h, then I've created client.cpp in which there's the inclusion of client.h and the definitions of its functions. Now, the compilation gives me these errors:
error C2504: 'Person': base class undefined client.h 7 1 Test
error C2440: 'inizialization': unable to convert from 'Client *' to 'person::impl::Person *' main.cpp 15 1 Test
error C2504: 'Person': base class undefined client.h 7 1 Test
error C2039: 'setName': is not a member of 'Client' client.cpp 8 1 Test
error C3861: 'sendMessage': identifier not found client.cpp 34 1 Test
It's a merely cut© refactoring but it doesn't work and I really don't understand WHY! What's the solution and why it gives me these errors? Is there something about C++ structure that I'm missing?
Here's a dog-n-bird implementation (ruff ruff, cheep cheep)
cLawyer is defined and implemented in main.cpp, while cPerson and cClient are defined in their own header files, implemented in their own cpp file.
A better approach would store the name of the class. Then, one wouldn't need to overload the speak method - one could simply set the className in each derived copy. But that would have provided in my estimates, a less useful example for you.
main.cpp
#include <cstdio>
#include "cClient.h"
class cLawyer : public cPerson
{
public:
cLawyer() : cPerson() {}
~cLawyer() {}
void talk(char *sayWhat){printf("cLawyer says: '%s'\n", sayWhat);}
};
int main()
{
cPerson newPerson;
cClient newClient;
cLawyer newLawyer;
newPerson.talk("Hello world!");
newClient.talk("Hello world!");
newLawyer.talk("Hello $$$");
return 0;
}
cPerson.h
#ifndef cPerson_h_
#define cPerson_h_
class cPerson
{
public:
cPerson();
virtual ~cPerson();
virtual void talk(char *sayWhat);
protected:
private:
};
#endif // cPerson_h_
cPerson.cpp
#include "cPerson.h"
#include <cstdio>
cPerson::cPerson()
{
//ctor
}
cPerson::~cPerson()
{
//dtor
}
void cPerson::talk(char *sayWhat)
{
printf("cPerson says: '%s'\n",sayWhat);
}
cClient.h
#ifndef cClient_h_
#define cClient_h_
#include "cPerson.h"
class cClient : public cPerson
{
public:
cClient();
virtual ~cClient();
void talk(char *sayWhat);
protected:
private:
};
#endif // cClient_h_
cClient.cpp
#include "cClient.h"
#include <cstdio>
cClient::cClient()
{
//ctor
}
cClient::~cClient()
{
//dtor
}
Output
cPerson says: 'Hello world!'
cClient says: 'Hello world!'
cLawyer says: 'Hello $$$'
Suggestions noted above:
//In the cPerson class, a var
char *m_className;
//In the cPerson::cPerson constructer, set the var
m_className = "cPerson";
//Re-jig the cPerson::speak method
void cPerson::speak(char *sayWhat)
{
printf("%s says: '%s'\n", m_className, sayWhat);
}
// EDIT: *** remove the speak methods from the cClient and cLawyer classes ***
//Initialize the clas name apporpriately in derived classes
//cClient::cClient
m_className = "cClient";
//Initialize the clas name apporpriately in derived classes
//cLaywer::cLaywer
m_className = "cLawyer";
You are declaring the class Client twice - once in the .h file and once in .cpp. You only need to declare it in the .h file.
You also need to put the using namespace person; to the .h file.
If class Person is in namcespace person, use the person::Person to access it.
The client.cpp must contain definitions only!
I think for the linker the class Client defined in client.h and class Client defined in client.cpp are different classes, thus it cannot find the implementation of Client::Client(). I purpose to remove the declaration of class Client from the client.cpp and leave there only definitions of functions:
// client.cpp
#include <time.h>
#include <ctype.h>
#include <string>
#include "client.h"
using namespace std;
Client::Client()
{
//DO STUFF
}
void Client::onMessage(const char * const message)
{
//DO STUFF
}
void Client::gen_random(char *s, const int len) {
//DO STUFF
}
I am compiling a logging program, but I am receiving this error and cant figure it out for the life of me...
logger.cpp:15: error: redefinition of ‘class Logger’
logger.h:20: error: previous definition of ‘class Logger’
with gcc when i compile with
g++ -Wall logger.cpp -o log
logger.h:
#ifndef LOGGER_H
#define LOGGER_H
#include <fstream>
#include <iostream>
#include <string>
using std::string;
class Logger
{
static Logger* m_pInstance;
public:
static Logger* Instance() { return m_pInstance; }
void writeLog(string message);
void openLogFile(string fileName);
void closeLogFile();
void deleteLogger();
};
#endif
logger.cpp
#include "logger.h"
#include <fstream>
#include <iostream>
class Logger
{
static Logger* m_pInstance;
std::ofstream m_pOutputFile;
Logger()
{
}
~Logger()
{
}
public:
static Logger* Instance()
{
if(!m_pInstance)
{
m_pInstance = new Logger;
}
return m_pInstance;
}
void writeLog(std::string message)
{
m_pOutputFile << message << "\n";
std::cout << "you just wrote " << message << " to the log file!\n" << std::endl;
}
void openLogFile(std::string fileName)
{
m_pOutputFile.open(fileName.c_str(),std::ios::out);
}
void closeLogFile()
{
m_pOutputFile.close();
}
void deleteLogger()
{
delete m_pInstance;
}
};
Logger* Logger::m_pInstance = NULL;
It's exactly what the error message says. The implementation file can't just provide a redefinition of the class adding new member variables and conflicting function bodies wherever it pleases. Instead, provide definitions for the functions and static member variables you've already declared.
#include "logger.h"
#include <fstream>
#include <iostream>
static Logger::Logger* m_pInstance;
Logger::Logger()
{
}
Logger::~Logger()
{
}
// this also is illegal, there's a body provided in the header file
//Logger* Logger::Instance()
//{
// if(!m_pInstance)
// {
// m_pInstance = new Logger;
// }
// return m_pInstance;
//}
void Logger::writeLog(std::string message)
{
m_pOutputFile << message << "\n";
std::cout << "you just wrote " << message << " to the log file!\n" << std::endl;
}
and so on
Well, because you are redefining the class. You can't say 'class Logger {' again in the .cpp when you already included it from the .h.
Compiler always expects only one class definition in the whole namespace(or scope) that class belongs to. Currently in the code you specified, you would see that there are infact 2 class definitions: one in .h file and another one in .cpp file. That is why the compiler is complaining that you are redefining a class which is not allowed.
Generally whenever you encounter a compiler error, it's a good idea to look at the lines that compiler tells. Most of the time the problem is in the line the compiler points out.