C++ how to extend class from different file without headers - c++

I’m trying to do a basic polymorphism program and am having some problems.
I have 2 files, Currency.cpp and Dollar.cpp
Currency.cpp looks something like this
#include <iostream>
using namespace std;
class Currency{
/* code */
};
Dollar.cpp looks something like this
#include <iostream>
using namespace std;
class Dollar : protected Currency{
/* code /*
};
When I try to build paths between the files (command shift b on mac) it tells me that Currency is not recognized as a class (in Dollar.cpp that is). I’m not supposed to use header files as this is for an assignment that specifies so. What am I supposed to do?
I use vs code on a 2020 m1 Mac if that has anything to do with it
Edit:
Thanks for all the feedback. From what I can tell what I'm asking here isn't possible. This assignment is for a data structures and algorithms class that accepts multiple languages, so maybe the teacher is rusty in c++ or something. I'm just gonna use header files and the professor will just have to deal with it lol.

I’m not supposed to use header files as this is for an assignment that specifies so.
The code will not work as shown. Dollar.cpp needs to know what the Currency class looks like in order to use it.
The ideal solution is to use a header file to share declarations across translation units, use the .cpp files to implement definitions, eg:
Currency.h:
#ifndef CurrencyH
#define CurrencyH
class Currency{
/* code */
};
#endif
Currency.cpp:
#include <iostream>
#include "Currency.h"
using namespace std;
// implement Currency's methods as needed...
Dollar.cpp:
#include <iostream>
#include "Currency.h"
using namespace std;
class Dollar : protected Currency{
/* code /*
};
But, since that is not an option for you, you have no choice but to copy the entire Currency class declaration into Dollar.cpp directly, and make sure it exactly matches the class declaration in Currency.cpp to avoid any ODR violations, eg:
Currency.cpp:
#include <iostream>
using namespace std;
class Currency{
/* code */
};
// implement Currency's methods as needed...
Dollar.cpp:
#include <iostream>
using namespace std;
class Currency{
/* code */
};
class Dollar : protected Currency{
/* code /*
};

Related

How to fix a C++ cyclical dependency with forward declaration in template class header

For teaching purposes in my applied oriented object courses, we are asked to develop a fully featured C++ application without using the STL nor any string manipulation functions from cstring (SDL for GUI will be involved in a later stage).
While redeveloping simple String and list container hierarchy classes, I encountered a cyclical dependency issue. Previously, I fixed these kind of issues using forward declaration. However, this time, things do not go as expected and this problem kept me busy for a few evenings now.
Here is a simple UML diagram of the issue I have.
Every class has their own .cpp and .hpp files, except for BaseListItemNotFoundException I declare with a using statement above the BaseList class declaration.
class BaseListItemNotFoundException: BaseException {
using BaseException::BaseException;
};
Even if this doesn't add any added pieces of info (IMHO), let me precise BaseList and HeplList classes are actually template classes defined using .ipp and .hpp.
I omitted some other classes involved to restrict the environment to a minimal working example (iterator and Cell generic class hierarchy used as payload for the lists). Header protections using define and ifndef conditions have been removed for clarity.
Here are a snipped of the files:
BaseList.hpp:
#include <cstddef>
#include <iostream>
#include "Cell.hpp"
class HeplString; // Forward declaration
#include "BaseException.hpp"
class BaseListItemNotFoundException: BaseException {
using BaseException::BaseException;
};
template<class T>
class BaseList {
// code
};
HeplList.hpp:
#include <cstddef>
#include "BaseList.hpp"
#include "Cell.hpp"
template<class T>
class HeplList : public BaseList<T> {
// code
};
#include "HeplList.ipp"
HeplString.hpp:
#include <cstddef>
#include <iostream>
#include <ostream>
#include <fstream>
#include "HeplList.hpp"
class HeplString {
// code
};
BaseException.hpp:
#include "HeplString.hpp"
#include "BaseList.hpp"
class BaseException {
// code
};
The main issue I have with this example is errors like this one:
src/tests/../BaseException.hpp:9:20: error: field ‘msg’ has incomplete type ‘HeplString’
HeplString msg;
^~~
In file included from src/tests/../HeplList.hpp:5,
from src/tests/../HeplString.hpp:9,
from src/tests/test.cpp:2:
src/tests/../BaseList.hpp:9:7: note: forward declaration of ‘class HeplString’
class HeplString;
^~~~~~~~~~
I don't understand what I'm doing wrong here. Reading other similar issues didn't help.
My git repository with the full code is available here, if needed: https://github.com/wget/hepl-2-cpp
Add #include "BaseException.hpp" to BaseList.hpp
Add #include "HeplList.hpp" to HeplString.cpp
Add the forward declaration template<class T> class HeplList; to HeplString.hpp
Now, you may need to modify some of your other classes which weren't including the BaseList.hpp header because they were relying on the header HeplString.hpp to do this for them.

How to organize includes includes in multiple Classes in C++

First I'm a beginner at programming so don't expect me to understand every code-specific word.
Second I'm sometimes slow on the uptake.
Third I think I covered the Basics of C++ but that's it. I'm happy to learn more of course!
To my Question:
I'm programming a little code to experience with classes. I made two classes, each one in a different .h and .cpp file. Now each one is using the headers iostream and string.
How should I include those without making any Problems? Is #pragma once sufficient?
Second question is about using namespace std:
where should i put it(I know it isn't a bad use but ist only for a small Programm)
First Header:
#pragma once
#include <iostream>
#include <string>
//using namespace std Nr.1
class one
{
};
Second Header:
#pragma once
#include <iostream>
#include <string>
//using namespace std Nr.2
class two
{
};
Finally Main:
#include "one.h"
#include "two.h"
//using namespace std Nr.3
int main()
{
return 1;
};
Thanks in advance for responding.
There's no problem including twice iostream and string in both class headers'.
The #pragma directive is used to protect two declarations of types (typedef, classes) of your own types.
Hence it applies to your class headers'.
Moreover, there are drawbacks using #pragma directive as stated here : https://stackoverflow.com/a/1946730/8438363
I recommend using preprocessor defines guards :
#ifndef __MY_HEADER__
#define __MY_HEADER__
//... your code here
#endif
Hope this helps.
You will need to use Include guards.They ensure the compiler includes each "included" header file(#include "XXX.h") only Once.
But if you are creating a small application & don't mind recompiling/rebuilding your entire project if need be, then putting the common header files in a dedicated header file is fair game & keeps code clean & small.
You can also make a header with all the common dependecies you need and include it in each class that needs those dependecies. Here is a simple example:
Core.h
#include <iostream>
#include <string>
// include most common headers
using namespace std;
One.h
#pragma once
#include "Core.h"
// if you need a header only for this class, put it here
// if you need a header in mutiple classes, put in Core.h
namespace one {
class One
{
public:
One();
~One();
void sumFromFirstNamespace(string firsNumber, string secondNumber)
{
//convert string to int
int first = stoi(firsNumber);
int second = stoi(secondNumber);
int result = first + second;
cout << result << endl;
}
};
}
Two.h
#pragma once
#include "Core.h"
// if you need a header only for this class, put it here
// if you need a header in mutiple classes, put in Core.h
namespace two{
class Two
{
public:
Two();
~Two();
void sumFromSecondtNamespace(string firsNumber, string secondNumber)
{
//convert string to int
int first = stoi(firsNumber);
int second = stoi(secondNumber);
int result = first + second;
cout << result << endl;
}
};
}
main.cpp
#include "One.h"
#include "Two.h"
int main()
{
one::One firstClass;
two::Two secondClass;
firstClass.sumFromFirstNamespace("10", "20");
secondClass.sumFromSecondtNamespace("20", "30");
}
There can be cases where you need the same 10+ headers in two different classes, i think that puting them in one header helps you see the code better.
And yes, preprocesor defines are also good, don't forget that. (:

C++ error code C2065: '<class name>' undeclared identifier, even though it should be declared in another .h-file

I have a multifile program, and I can't figure out why my program says that "Customers" (in the registerNewUser() function) is an undeclared identifier.
proc.h
#ifndef PROC_H
#define PROC_H
#include <iostream>
#include "const.h"
#include "customers.h"
#include <fstream>
using namespace std;
void registerNewUser(Customers cBase); // Add new user.
#endif // !PROC_H
I have included the header file (customers.h) with the Customers class also.
customers.h
#ifndef CUSTOMERS_H
#define CUSTOMERS_H
#include <iostream>
#include "const.h"
#include "proc.h"
#include "customer.h"
using namespace std;
class Customers {
private:
char* current;
List* customerList; // List for customers.
public:
Customers(); // Constructor.
~Customers(); // Destructor.
void handler(); // Customers handler/menu.
void addNew(char username[]);
};
#endif // !CUSTOMERS_H
Can anyone see what's wrong?
You have a circular include. customers.h includes proc.h so basiacally
void registerNewUser(Customers cBase);
Will get added to customers.h before the compiler has seen what a Customer is. It looks like you should just be able to remove the #include "proc.h" in customers.h and it should compile.
As stated in the comments above you should never use using namespace std; in a header file as anything that includes it now has the entire std namespace exposed. You should also get in the habit of only using it in the most narrow scope you can or drop it completely. For further reading on the use of using namespace std; see Why is “using namespace std” in C++ considered bad practice?
Basically including "customers.h" in "customers.h" wouldn't be a problem here, since you have a guard (plus point for that). Nevertheless it is not very nice.
As NathanOliver said it COULD be a problem with the order of the includes but it doesn't have to. If you include proc.h first everything is fine. If you include customers first, the compiler includes proc.h before he sees the customer class. proc then wont include customers.h (since its guard prevents it). Then he will find your function not knowing what "Customer" means. So depending on the include order of your header files it will or will not work.
If you want a hint: I normally first only include the necessary files for a forward declaration, then do a forward declaration. Then I include the files necessary files for the definition of the class (These will already know that the class exists). The complete class declaration (with member function declaration) follows. If you do it like this you can avoid many mistakes. In your case:
#ifndef CUSTOMERS_H
#define CUSTOMERS_H
class Customers;
#include "proc.h"
#include "ListTool2B.H"
using namespace std;
class Customers
{
private:
char* current;
List* customerList; // List for customers.
public:
Customers(); // Constructor.
~Customers(); // Destructor.
void handler(); // Customers handler/menu.
void addNew(char username[]);
};
#endif
This is probably a duplicate: you have proc.h including customers.h and customers.h including proc.h this will cause a circular reference, and looks like proc.h included in customers is not necessary, so you could try simply to delete this line:
#include "proc.h"

Global namespace is not checked in other namespaces

I'm trying to use namespaces in my code so I have a header file that looks like this :
#include <string>
namespace AppNamespace
{
class A
{
std::string name;
};
}
When I try to compile this, it says "'string' is not a member of AppNamespace::std". If I remove the std:: in front of string, or if I write ::std::string name, then it will compile fine.
This is of course a simplified example, I have many header files and not all of them show this behavior. I am not sure what can cause this, I thought that the compiler would always try the global namespace as well.
I am currently using Visual Studio 2012 if this matters.
This is of course a simplified example, I have many header files and not all of them show this behavior. I am not sure what can cause this, I thought that the compiler would always try the global namespace as well.
At some point you must have something like this:
namespace AppNamespace
{
#include <string> // or #include "my_header" which in turn includes <string>
class A
{
std::string name;
};
}
The #include directive does not respect namespaces. You need to move them all out to the global namespace scope, or each (possibly nested) inclusion of a standard header will cause undefined behavior in the form of creating a nested namespace std.
Using:
using namespace std;
#include <iostream>
#include "test_header.h"
int main() ...
The code compiles either way with your above example as a header.
Moving
using namespace std;
below the header file (in my case test_header.h) will cause it to fail if I don't use std::string.
Is that the problem you are having?

Invalid use of undefined type 'struct PelephonePH'

i have received in .cpp errors of invalid use of undefined struct PelephonePN, CellcomPN and so on
and also error in .h errors of forward declaration of PelephonePN,...
#ifndef PHONE_H_INCLUDED
#define PHONE_H_INCLUDED
#include <iostream>
#include <ctime>
#include <string>
#include "phone.h"
using namespace std;
class PhoneNumber;
class PelephonePN;
class CellcomPN;
class OrangePN;
class HotPN;
class BezeqPN;
class PhoneManager
{
private:
PelephonePN* mpPelephone;
CellcomPN* mpCellcom;
OrangePN* mpOrange;
HotPN* mpHot;
BezeqPN* mpBezeq;
public:
PhoneManager();
~PhoneManager();
void split_check_data(string str);
};
#endif
and .cpp
#include <iostream>
#include <ctime>
#include <string>
#include <sstream>
#include "phone_manager.h"
#include "phone.h"
using namespace std;
PhoneManager::PhoneManager()
{
srand(time(0));
mpPelephone = new PelephonePN();
mpCellcom = new CellcomPN();
mpOrange = new OrangePN();
mpHot = new HotPN();
mpBezeq = new BezeqPN();
mpPelephone->add(mpCellcom);
mpPelephone->add(mpOrange);
mpPelephone->add(mpHot);
mpPelephone->add(mpBezeq);
mpBezeq->setNext(mpPelephone);
}
To instantiate an object, forward declaration is just insufficient. Include the corresponding headers in the source file. In the body of the constructor, you are instantiating mpPelephone, ..... So, make sure that corresponding class headers can be seen in the translation unit.
In your .cpp source file you need to #include the headers that define class PelephonePN and its associates.
It is fine to forward-declare these classes in the header if you are only using them as pointers or references, but one you start using them in your implementation, you'll need to provide the compiler with the definition.
You can't use a forward declaration of a class to access its members (which includes the constructor, default or otherwise) or its size and without those two things, you can't instantiate an instance of that class.
You require its FULL implementation to do that, so in your .cpp file you need to include the header with the whole class PelephonePN {/* class body */}; section.
in the first file you have lines:
#ifndef PHONE_H_INCLUDED
#define PHONE_H_INCLUDED
I suppose you have same lines in phone.h, please check...
Are your PelephonePN and co. in a particular namespace? If so, predeclarations must all be in the same namespace. Since you added a using namespace std (sigh), my guess is that phone.h is defining your classes inside the namespace std (I hope it doesn't, but that's another thing).
If so, your predeclarations must be:
namespace std {
class PelephonePN;
}
Btw, what is a pelephone??? O.O