I'm running into a lot of problems with this, primarily being that my passed Vector of my Class keeps getting flagged as an undeclared identifier. Any help on solving the problem or explanations to help me figure out what I don't understand would be greatly appreciated.
So here is a simplified version of what I have now:
main.cpp
#include "functions.h"
#include "vehicle.h"
int main()
{
int menuSelection;
vector<Vehicle> inventory;
do
{
cout << "Please make a selection:" << endl << endl;
cout << "1: Display Inventory" << endl;
.......
cout << "8 : Write inventory to file and exit" << endl << endl;
if (menuSelection == 1)
{
if (inventory.empty())
cout << "Database empty" << endl;
else
display(inventory);
.......
} while (menuSelection != 8);
return 0;
}
vehicle.h
#pragma once
#include "functions.h"
class Vehicle
{
private:
string VIN;
int year;
.......
// public:
// string getVIN();
.......
}
functions.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void display(vector<Vehicle>);
.......
void display(vector<Vehicle>& in)
{
Vehicle v;
cout << "VIN: " << v.getVIN(in)
}
.......
I've tried a bunch of different things to get it to work so that's why a lot of stuff may seem like odd syntax (I'm also not very good). My assignment is to have a menu in main.cpp which will create a vector from a class stored in vehicle.h, and then the menu is supposed to call functions which are located in functions.h that will communicate through vehicle.h to a fourth not included vehicle.cpp to work with information from the class.
In functions.h, void display(vector<Vehicle>); does not compile because Vehicle is undeclared at this point.
Also, in functions.h, void display(vector<Vehicle>& in) is a different overload to the previous prototype (the & makes a difference), probably not what you intended. And then you place a function body in functions.h -- this should not be there.
You need to organize your code so that Vehicle class definition appears, and then functions.h includes that.
So vehicle.h should look like:
#pragma once
#include <string>
// do NOT include functions.h
class Vehicle
{
// ...
};
and then functions.h should look like:
#pragma once
#include "vehicle.h"
// do NOT do "using namespace std;" in a header and don't include any unnecessary headers
void display(vector<Vehicle> &in);
and then functions.cpp should #include "functions.h" and contain the function body for display.
undeclared identifier means the compiler sees a name but don't see a declaration of that name (as a variable, class, function, etc.). It happens in your code in a few places, for example:
MyClass is used but not declared (main.cpp)
Vehicle is used but not declared (functions.h)
You use Vehicle.v but v not declared in class Vehicle (in addition, I doubt that this is what you intended - if you use class name Vehicle.v it means accessing a static variable, as opposed to vehicle.v).
It seems you lack some basic background. The most important thing is that you learn to decipher compiler errors, so at least you understand what went wrong.
Related
I'm trying to finish a C++ school assignment and I have a question that I have an issue that may be simple. I have constructed all the files (more than below which felt was unnecessary to add) from scratch and I am left scratching my head. I'm told to create a private dynamic array of objects that will be defined by user input. This will be in the "student.cpp" file. This dynamic array is to create the objects that will operate the "course.cpp" file. I have attempted a large series of workarounds, but have not found the answer and expect the answer to be obvious. Here is the trimmed down version of my code. I also commented where the issue is in the student.cpp file and the other points of possible issue.
Any suggestions will be appreciated. I manually typed this again, so if it appears there was a typo, my apologies in advance. I will edit if I notice anything after the initial post.
//source.cpp
#include <iostream>
#include "student.h"
using namespace std;
void main() {
student stu;
stu.printRecord();
}
//student.h
#ifndef STUDENT_H
#define STUDENT_H
#include<iostream>
#include<string>
#include "course.h"
using namespace std;
class student{
public:
student();
void printRecord();
~student();
private:
string name;
int numCourses;
course* stuCourses; //possible source of error
};
#endif
//student.cpp
#include "student.h"
student::student(){
cout << "enter name: ";
getline(cin,name);
cout << "Enter the number of courses the student is taking: ";
cin >> numCourses;
course* stuCourses= new course[numCourses]; //possible source of error (now this->stuCourses = new course[numCourses];)
}
void student::printRecord(){
cout << endl << name << endl;
course::printCourse(); //Error at this point
}
//course.h
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
using namespace std;
class course{
public:
course();
void printCourse();
~course();
private:
string title;
};
#endif
//course.cpp
#include <iostream>
#include "course.h"
course::course(){
cout << "Title: ";
cin >> title;
}
void course::printCourse(){
cout <<title;
}
course::~course(){}
Again, any help is appreciated. Thanks for looking even if you don't respond.
class course{
public:
course();
void printCourse();
~course();
private:
string title;
};
Here you defined printCourse as a non-static-method of the class course.
But where the error occurs: course::printCourse() you're trying to execute a static method of the class Course. If you don't know what I'm talking about here is a short summary (but i recommend reading about the differences between static and non static methods):
A static method works without an instance of the class. This is commonly used on singletons which are by design "just one single object". This could be for example a global ID-Counter for the students:
class StudentIdManager
{
static int num_students = 0;
public:
static int getNextStudentId()
{
return num_students++;
}
}
You can now get the next unique id for a student by calling StudentIdManager::getNextStudentId() without an actual object. You could call it a "class function". Not an "object function".
A static class is obviously not suitable for your course, so it makes sense for your to implement it like you did.
However, you have to call it on an actual object. The difficulty is to find each object in the dynamically allocated array, but you should have every info you need. In the end it would look something like this:
void student::printRecord()
{
cout << endl << name << endl;
for (size_t i = 0u; i < numCourses; i++)
{
// here you're now calling the method printCourse on an actual course as intended instead of a static class
stuCourses[i]->printCourse();
}
}
However I also find it weird that you have to implement this. A simple std::array<course, numCorses> for a fixed number of courses, or a std::vector<course> for a variable number of courses would make the code way more readable, safe and extensible.
What you're doing here would is a nice task for C to get used to the Von Neuman Architecture.
But not for C++. It's not the same. Sadly for most teachers C++ is "C with classes" which is just wrong on so many levels. All the features C++ added where there for you to not write code like your teacher wants.
Instead of:
course* stuCourses= new course[numCourses];
Can use:
this->stuCourses = new course[numCourses];
Or even:
stuCourses = new course[numCourses];
Sorry new to C++ here and cannot find the answers that I am looking for anywhere. I am trying to run the simplest possible program in C++ using OOP and multiple files. If the Vehicle class has no doSomething() function in it, then the constructor prints out just fine. When I add the function and call car.doSomething() it just gives me errors. I have searched for days and can't find a working answer.
main.cpp
#include <stdio.h>
#include <iostream>
#include "Vehicle.h"
using namespace std;
int main(int argc, char **argv){
Vehicle car;
car.doSomething();
return 0;
}
Vehicle.cpp
#include "Vehicle.h"
Vehicle::Vehicle(){
cout << "do something" << endl;
}
void doSomething(){
cout << "do something else" << endl;
}
Vehicle.h
#pragma once
#include <iostream>
using namespace std;
class Vehicle{
public:
Vehicle();
void doSomething();
};
Like I said, new to C++ and not sure how to fix this. Thanks for any help.
Specs:
Codelite v10.0.0,
Linux Ubuntu 18.04
Error: undefined reference to 'Vehicle::doSomething()'
You didn't need to search for days; you only needed to read the chapter in your C++ book about defining member functions.
It goes like this:
void Vehicle::doSomething()
{
cout << "do something else" << endl;
}
That Vehicle:: is how the computer knows that this doSomething definition is for the class Vehicle (just like you did already with the constructor).
Without that, it's just an ordinary function. It doesn't matter that the file is called Vehicle.cpp; C++ doesn't really care about filenames. You could have all sorts of functions, variables, class definitions etc in that file, regardless of whether it were called Vehicle.cpp or Stuff.cpp or Lightness4Eva.cpp (that's not to say that your naming convention is ungood, though!).
I suppose you have "unresolved" linker error in this case. It means error is not in runtime but in build time. Error message could prompt you that linker can't find Vehicle::doSomething(). This would point you that you didn't actually provide doSomething() function. Read error outputs, it helps to understand what is wrong.
write doSomting() defination with class name as in .cpp file:
void Vehicle::doSomething()
{
cout << "do something else" << endl;
}
So I have the following code in a header file named Classes.h:
#ifndef CLASSESS_H
#define CLASSESS_H
class PalindromeCheck
{
private:
string strToCheck;
string copy;
public:
PalindromeCheck(string testSubject) : strToCheck(testSubject) {} //Constructor
void Check()
{
copy = strToCheck; //Copy strToCheck into copy so that once strToCheck has been reversed, it has something to be checked against.
reverse(strToCheck.begin(), strToCheck.end()); //Reverse the string so that it can be checked to see if it is a palindrome.
if (strToCheck == copy)
{
cout << "The string is a palindrome" << endl;
return;
}
else
{
cout << "The string is not a palindrome" << endl;
return;
}
}
};
#endif
And now I have the following code in a source file:
#include <iostream>
#include <string>
#include <algorithm>
#include "Classes.h"
using namespace std;
int main()
{
PalindromeCheck firstCheck("ATOYOTA");
firstCheck.Check();
return 0;
}
When I compiled this code using the Visual C++ Compiler, I got a ton of errors messages that all stemmed from these first four:
'strToCheck': unknown override specifier
missing type specifier - int assumed.
'copy': unknown override specifier
missing type specifier - int assumed.
I tried adding in #include <string> into the header file and recompiled it but it did absolutely nothing. This confuses me because I thought I could use a string as a datatype, but apparently not in a class? It would be great if someone could help me out because I don't know why my code isn't working.
You need to #include <string> in the class header itself.
You also need to either use the std:: namespace (preferable) or also add using namespace std to that header as well (which I strongly discourage).
Here is my file.h :
#define MAXCOMPONENTS 20
#include <string>
#include <string.h>
#include <iostream>
class file{
public:
file(char const * filename);
virtual ~file();
void Takeinfocomponents();
void Takeshape();
void Getvalue(int i);
char *Getcomponents();
char *Getcolor();
protected:
private:
char const * filename;
String shape;
int value[MAXCOMPONENTS];
char components[MAXCOMPONENTS];
char color[MAXCOMPONENTS];
};
And my file.cpp :
#include <fstream>
#include <iostream>
#include <string.h>
#include <string>
#include "file.h"
using namespace std;
file::file(char const* filename)
{
cout << "constructor/fichier:" << filename << endl;
ifstream fichier(filename,ios::in);
if(fichier){
this->filename=filename;
fichier.close();
Takeshape();
Takeinfocomponents();
}else{
cout << "File name invalid." << endl;
}
}
file::~file()
{
}
char* file::Getcolor(){
return this->color;
}
char* file::Getcomponents(){
return this->components;
}
void file::Getvalue(int i){
cout << this->value[i] << endl;
}
void file::Takeinfocomponents(){ // pic up name of components, his number and his color
cout << "Takeinfocomponents/fichier:" << filename << endl;
ifstream fichier(this->filename,ios::in);
ifstream stop(this->filename,ios::in);
string line;
int i=0;
getline(fichier,line);
getline(stop,line);
getline(stop,line);
while(line!="/" && i!=99){ // take all informations while the stop signal isn't read
getline(stop,line);
fichier >> this->components[i] >> this->value[i] >> this->color[i];
cout << this->components[i] << this->value[i] << this->color[i] << endl;
i++;
}
fichier.close();
}
void file::Takeshape(){ // pic up the shape in .txt
cout << "Takeshape" << endl;
fstream fichier(this->filename,ios::in);
string shape;
fichier >> shape;
this->shape=shape;
fichier.close();
}
This is a part of a larger programm who make graphic from informations ( from the .txt ), this part is use to pic up informations from the .txt.
The problem come from the declaration of the :
String shape;
He told me that string is not a name type. I've tried with a small "s" :
string shape;
But this ain't working.
I've the impression that i miss a very small things that could unlock my problem.
Thx for help.
Notabene : I'm french and my english is not this good, please answer like i was a little child ahah !
You have to explicitly state the namespace:
std::string shape;
You shouldn't pollute the namespace in the headers, so using namespace std is not an option here.
See also the question about namespace pollution. If you just need strings, prefer to use
using std::string;
in the cpp file.
C++ uses the concept of a namespace. A namespace is used to group types, variables, etc. together in a meaningful way, regardless of the number of header files those types or variables are spread across.
In this example, the string type is inside the std namespace. std is short for Standard Template Library, and it is the namespace that most of C++'s library classes, etc. are stored in.
The correct way of accessing type inside a namespace is namespace::type, so the correct way of accessing the string type inside the std namespace is std::string. You can also write using namespace std to access the types in std without having to write std:: each time, but doing this in a global scope is a bad idea, because it pollutes the global namespace.
In the code you posted, string shape; appears before using namespace std, as the #include "file.h" appears before it. Therefore, it won't take effect.
To be able to use the string class and create string objects, you need to include...
#include <string>
... at the top of your header files.
You do not need...
#include <string.h>
The string class, like all STL classes, is part of the std namespace. If you do not want to write std:: before every class name, you can simply state...
using namespace std;
... at the top of your header files so that instead of...
std::string shape;
... you can simply use...
string shape;
I'm working on making a game in C++. I have declared a Constant namespace used for global values that I need access to throughout the program. In there I have an ofstream for debugging purposes (yeah, I know it's not "constant" but it fits best there), which outputs only when it feels like it. I was able to make a small program demonstrating the problem. I apologize for it being spread across 4 files, but it is important, I promise.
main.cpp:
// Include necessary files
#include "test.h"
#include "constants.h"
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
// Start of program
Constant::outstream.open("test.txt");
// ...
// Do stuff
// Output debugging info
Test test;
test.print("Test", Constant::outstream);
// ...
// Do other stuff
// End of program
Constant::outstream.close();
return 0;
}
constants.h:
#ifndef _CONSTANTS_H
#define _CONSTANTS_H
#include <fstream>
namespace Constant
{
static ofstream outstream;
}
#endif
test.h:
#ifndef _TEST_H
#define _TEST_H
#include <string>
#include <fstream>
#include "constants.h"
class Test
{
public:
void print(string str, ofstream& out);
};
#endif
test.cpp:
#include "test.h"
using namespace std;
void Test::print(string str, ofstream& out)
{
out << "out: " << str << endl << flush; // Works
Constant::outstream << "Constant::outstream: " << str << endl << flush; // Doesn't
}
In the test.cpp file, the out << ... line works as it should, while the Constant::outsream << ... line doesn't do anything even though I'm passing Constant::outstream as the out parameter! I don't see any reason why these two lines should be in any way different.
Before posting this, I tried putting test.cpp's code in test.h, just to have less files for the question, and was amazed to see it work. If I copy-paste the Test::print() function into test.h (whether inside or out of the class Test { ... }), then both output commands work correctly. the problem only occurs if Test::print()'s implementation is in a separate file.
It seems like any references to Constant::outstream simply don't work in class cpp files (no compile error, just nothing happens). It works in main.cpp and in class header files, but any class cpp file it seems not to. Unfortunately, this is a big program I'm writing so pretty much every class has its own cpp implementation file, and that's really the one place I need to use this ofstream. Does anyone know the reason for this?
Thanks in advance,
Doug
Constant::outstream has internal linkage, thus a separate instance is created for each translation unit. In short, Constant::outstream in test.cpp and main.cpp are two different variables.
§3.5.2 A name having namespace scope (3.3.6) has internal linkage if it is the name of
— a variable, function or function template that is explicitly declared static; or,
On the other hand, static class members would be visible throughout the program.
So, if you would write
struct Constant
{
static ofstream outstream;
}
instead of
namespace Constant
{
static ofstream outstream;
}
it would work.
However, note that the class must have external linkage; e.g. you should not put in in anonymous namespace.