I've been trying to define an error class in C++. I have three files; main.cpp, my_class.h, my_class.cpp. If I tried to compile with the below code, all, of course, in three separate files, I would get a multiple definition error of my_exception.
Please note, if I move the entire definition and declaration of my_exception into my_class.cpp, everything compiles fine and works correctly. Why is this, and how should I write this so that I could put the definition of the exception into the .h file? Or should I even put an error class definition into a .h file?
main.cpp:
#include my_class.h
int main(){
my_class m;
/* stuff */
}
my_class.h:
#ifndef MY_CLASS_H
#define MY_CLASS_H
#include <iostream> //irrelevant for this
#include <exception>
using namespace std;
//taken from http://www.cplusplus.com/doc/tutorial/exceptions/
class my_exception : public exception{
virtual const char* what() throw() { return "message";}
} me_err;
class my_class{
my_class() };
};
#endif // MY_CLASS_H
my_class.cpp:
#include my_class.h
my_class::my_class(){
throw me_err;
}
The problem you are having is you created a global variable in your header file. When you compile main.cpp and my_class.cpp each one of them now has the same global variable. To fix this you can make me_err a member of my_class since that is what is using it.
Edit:
As pointed out by Fred Larson you could get rid of me_err entirely and just use throw my_exception;
Related
I made a smaller reproducible version of the code that gave me these errosr: 'MyNamespace::MySecondClass': 'class' type redefinition, 'print': is not a member of 'MyNamespace::MySecondClass'. Is there any way of working around this problem?
// MyClass.h
#pragma once
namespace MyNamespace {
class MySecondClass {};
}
// MyClass.cpp
#include "MyClass.h"
#include <iostream>
using namespace std;
class MyNamespace::MySecondClass
{
public:
void print(const char* msg)
{
cout << msg << endl;
}
};
The problem is that in MyClass.h you define a class MySecondClass as an empty class. When you the define your class in MyClass.cpp you give a different definition, which contains some new members. This infringes the One Definition Rule (ODR).
Solution 1
remove {} in the header. This will tell the compiler that you declare that such a class exists but that it will be defined later. Your code would compile. Unfortunately if you’d include the header in other cpp, these could make only a very very limited use of MySecondClass.
Solution 2
define in the header the class with all its members (but without providing the implementation of the member functions:the signature is sufficient). This would allow the class to be used in whichever cpp that
would include it:
// MyClass.h
#pragma once
namespace MyNamespace {
class MySecondClass {
public:
void print(const char* msg);
};
}
You’d then define the members of the class in its cpp in the appropriate namespace:
// MyClass.cpp
#include <iostream>
#include "MyClass.h"
using namespace std;
namespace MyNamespace {
// member functions
void MySecondClass::print(const char* msg)
{
cout << msg << endl;
}
}
Remark: the include sequence in the cpp should first include the standard library headers, then only your own headers. It makes no difference in your simple example, but better get used the good practices immediately.
I have a very simple program that doesn't compile due to multiple definition error. It is here:
main.cpp
#include <iostream>
#include "read_p.h"
using namespace std;
int main()
{
return 0;
}
read_p.cpp
#include "read_p.h"
using namespace std;
void read_p()
{
/*
some code here
*/
}
read_p.h
#ifndef READ_P_H
#define READ_P_H
#include "buildings.h"
void read_p();
#endif
buildings.h
#ifndef BUILDINGS_H
#define BUILDINGS_H
#include "flag.h"
using namespace std;
/*
some class here
*/
#endif
flag.h
#ifndef FLAG_H
#define FLAG_H
using namespace std;
class
Test
{
private:
public:
int test_var;
Test(int);
};
Test::Test(int a)
{
test_var = a;
}
#endif
The compiler gives me the error that the constructor Test::Test is defined multiple times. Unlike questions I find online, this error is not due to including the cpp-file instead of the h-file.
Question: Where does the multiple definition of the constructor occur? And is the proper way to circumvent the issue by making the constructur inline?
Change
Test(int);
to
inline Test(int);
Even better, fix your class definition to define member functions inline, which makes them implicitly inline:
class Test
{
public:
int test_var;
Test(int a) : test_var(a) {}
};
Otherwise, as always, defining a function in a header means that it gets defined in every translation unit that includes that header, which leads to multiple definitions.
I have a very simple program that doesn't compile due to multiple definition error. It is here:
main.cpp
#include <iostream>
#include "read_p.h"
using namespace std;
int main()
{
return 0;
}
read_p.cpp
#include "read_p.h"
using namespace std;
void read_p()
{
/*
some code here
*/
}
read_p.h
#ifndef READ_P_H
#define READ_P_H
#include "buildings.h"
void read_p();
#endif
buildings.h
#ifndef BUILDINGS_H
#define BUILDINGS_H
#include "flag.h"
using namespace std;
/*
some class here
*/
#endif
flag.h
#ifndef FLAG_H
#define FLAG_H
using namespace std;
class
Test
{
private:
public:
int test_var;
Test(int);
};
Test::Test(int a)
{
test_var = a;
}
#endif
The compiler gives me the error that the constructor Test::Test is defined multiple times. Unlike questions I find online, this error is not due to including the cpp-file instead of the h-file.
Question: Where does the multiple definition of the constructor occur? And is the proper way to circumvent the issue by making the constructur inline?
Change
Test(int);
to
inline Test(int);
Even better, fix your class definition to define member functions inline, which makes them implicitly inline:
class Test
{
public:
int test_var;
Test(int a) : test_var(a) {}
};
Otherwise, as always, defining a function in a header means that it gets defined in every translation unit that includes that header, which leads to multiple definitions.
Below are by 4 classes, I'm learning about basic c++ syntax and boy is it much harder and less forgiving than other languages I have used. I have a main class, base class "BaseArray" and two sub classes "OrderedArray" and "UnorderedArray".
Main.cpp
#include <iostream>
#include "OrderedArray.cpp"
#include "UnorderedArray.cpp"
using namespace std;
int main() {
system("PAUSE");
return 0;
}
BaseArray.cpp
#include <iostream>
using namespace std;
class BaseArray {
public:
BaseArray::BaseArray() {
}
};
OrderedArray.cpp
#include <iostream>
#include "BaseArray.cpp"
using namespace std;
class OrderedArray : public BaseArray {
OrderedArray::OrderedArray() {
}
};
UnorderedArray.cpp
#include <iostream>
#include "BaseArray.cpp"
using namespace std;
class UnorderedArray : public BaseArray {
UnorderedArray::UnorderedArray() {
}
};
The errors I receive are as followed, from scouting other threads online. I think it might have to do with duplicate calling of classes. To be honest, I have no clue. If someone could point me in the right direction that would be nice, thanks in advance!
error C2011: 'BaseArray':'class' type redefinition
error C2504: 'BaseArray':base class undefined
To fix this error I can remove one of the includes at the top of main.cpp, but I need those to create objects and call functions from the subclasses later on.
You should put your base array in a header:
BaseArray.h
#ifndef BASEARRAY_H_GUARD // include guard
#define BASEARRAY_H_GUARD // include guard
// no using namespace !!
// only includes needed for what's in the header
class BaseArray {
public:
BaseArray();
};
#endif // include guard
And then leave in the cpp only the implementation part of your class:
BaseArray.cpp
#include <iostream>
#include "BaseArray.h"
using namespace std;
BaseArray::BaseArray() { // no need class enclosing: the BaseArray:: prefix is sufficient
}
The you can apply the same principle to the derived classes:
OrderedArray.h
#ifndef BASEARRAY_H_GUARD // include guard
#define BASEARRAY_H_GUARD // include guard
#include "BaseArray.h" // include only those that you need but all those that you need
class OrderedArray : public BaseArray { // requires BaseArray
OrderedArray();
};
#endif
OrderedArray.cpp
#include <iostream> // include headers that are needed for class implementation
#include "OrderedArray.h" // this should be self contained and provide
// evertyhing that is needed for the class itself
using namespace std;
OrderedArray::OrderedArray() {
}
You then have to do the same for UnorderedArray and finally, you have to adapt your main.cpp to include .h instead of .cpp. And you're done.
A final remark: your cpp source code files are now ready for separate compilation. This means that you can no longer compile only main.cpp, hoping that it includes all the code: you have now to compile the 4 cpp files and link them together.
I'm starting to learn C++ (coming from Java), so bear with me.
I can't seem to get my method declaration to accept a class I've made.
'Context' has not been declared
I think I'm not understanding a fundamental concept, but I don't know what.
Expression.h
#include "Context.h"
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
};
Context.h
#include <stack>
#include <vector>
#include "Expression.h"
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
};
You have to forward declare Expression in Context or vice versa (or both), otherwise you have a cyclic dependency. For example,
Expression.h:
class Context; // no include, we only have Context*.
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
};
Context.h:
#include <stack>
#include <vector>
class Expression; // No include, we only have Expression*
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
};
You can perform the forward declarations because the full definition of the classes isn't needed, since you are only referring to pointers to the other class in each case. It is likely that you will need the includes in the implementation files (that is, #include "Context.h" in Expression.cpp and #include Expression.h in Context.cpp).
Finally, remember to put include guards in your header files.
In C++, class definitions always have to end with a semi-colon ;
so example:
class foo {};
Java and C# doesn't require that, so I can see your confusion.
Also it looks like both your header files include each other. Thus it's kind of like a snake eating it's tail: Where does it start? Thus in your Expression.h you can replace the 'include' with a forward declaration instead:
class Context;
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
}
And last but not least, you should put a compiler guard to prevent the header from getting included more than once into a .cpp file. You can put a #pragma once in the top of the header file. That is useful if you are using visual studio and the microsoft compiler. I don't know if GCC supports it or not. Or you can wrap your header file like this:
#ifndef EXPRESSION_H_
#define EXPRESSION_H_
class Context;
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
}
#endif
you might need to forward declare the classes Context and Expression in the header files before the #include
e.g.
#include <stack>
#include <vector>
// forward declaration
class Context;
class Expression;
#include "Expression.h"
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
}