Linking a class when used inside another class - c++

When I have a class I want to use somewhere else, such as Secondaryfile.cpp, I can import it fine into another file where I create a new class, as long as I do the class definition, etc inside the .cpp file, not the header file, otherwise I get linking errors. I have tried adding things like extern "C" in the Secondaryfile.cpp but to no avail. Looking at the errors, I also thought that pershaps I shouldn't use the namespace, however, that still results in the same error.
The reason why I am doing this is that I want to import a Tertiaryfile into Mainfile which has a function with the same name as a function in Secondaryfile, so I wanted to be able to refer them as, say, Secondaryfile::add1() and Tertiaryfile::add1() and avoid any issues with the same names that way - through the use of namespaces. I want to be able to declare the Mainfile class in its header file so that I can import it and use it in a different class down the line.
In the example below, running g++ Mainfile2.cpp compiles fine, however, g++ Mainfile.cpp doesn't, instead it results in the following error:
Mainfile.cpp:(.text+0x20): undefined reference to 'Secondaryfile::Secondaryfile::Secondaryfile()'
Mainfile.cpp:(.text+0x58): undefined reference to 'Secondaryfile::Secondaryfile::getX()'
Mainfile.cpp:(.text+0x7a): undefined reference to 'Secondaryfile::Secondaryfile::Secondaryfile(int)'
My code:
Mainfile.cpp
#include "Mainfile.h"
#include <cstddef>
#include <cstdio>
Mainfile::Mainfile(char* name, Secondaryfile::Secondaryfile x)
{
this->name = name;
this->x = x;
}
Mainfile::getDoubleX(){
return this->x.getX() * 2;
}
static Secondaryfile::Secondaryfile getObj(int num){
return Secondaryfile::Secondaryfile(num);
}
int main(){
}
Mainfile.h
#ifndef MAINFILE_H
#define MAINFILE_H
namespace Secondaryfile{
#include "Secondaryfile.h"
}
class Mainfile
{
public:
char* name;
Secondaryfile::Secondaryfile x;
Mainfile(char*, Secondaryfile::Secondaryfile);
int getDoubleX();
static Secondaryfile::Secondaryfile getObj(int);
};
#endif
Mainfile2.cpp
namespace Secondaryfile{
#include "Secondaryfile.h"
}
#include "Mainfile2.h"
#include <cstddef>
#include <cstdio>
class Mainfile2{
public:
char* name;
Secondaryfile::Secondaryfile x;
Mainfile2(char* name, Secondaryfile::Secondaryfile x)
{
this->name = name;
this->x = x;
}
getDoubleX(){
return this->x.getX() * 2;
}
static Secondaryfile::Secondaryfile getObj(int num){
return Secondaryfile::Secondaryfile(num);
}
};
int main(){
}
Mainfile2.h
#ifndef MAINFILE2_H
#define MAINFILE2_H
int getDoubleX();
static Secondaryfile::Secondaryfile getObj(int);
#endif
Secondaryfile.cpp
#include "Secondaryfile.h"
#include <cstddef>
#include <cstdio>
Secondaryfile::Secondaryfile(int x)
{
this->x = x;
}
Secondaryfile::Secondaryfile()
{
this->x = 0;
}
int Secondaryfile::getX()
{
return this->x;
}
int Secondaryfile::add1(int num)
{
return num+1;
}
int main(){
}
Secondaryfile.h
#ifndef SECONDARYFILE_H
#define SECONDARYFILE_H
class Secondaryfile
{
public:
int x;
Secondaryfile();
Secondaryfile(int);
int getX();
static int add1(int);
};
#endif

There are many problems with your code.
In Mainfile.cpp you didn't specify the return type of Mainfile::getDoubleX()(it should be int)
You can only specify static member functions inside a class definition(in Mainfile.cpp, the function getObj has that qualifier). Also it should have a class scope, so the correct way of writing is Secondaryfile Mainfile::getObj(int num)
Doing namespace Secondaryfile{ #include "Secondaryfile.h"}. You shouldn't do this. Just #include "Secondaryfile.h" inside the source files is enough. You mention that you did this to prevent "linking errors", but that is probably because of the other problems in your code and in your project configuration.
You also didn't specify your compiler & IDE/cmake/makefile configs, which is essential for properly compiling and linking these header and source files.
Are you building a library or executable code? You include a main() function in your source files that doesn't do anything, which is also bad practice, because main() in C++ is an entry-point function, wich means that the compiler will look for it to create the starting point of the program1.
With these in mind, I tried to fix your code. See if this is what you had in mind:
Mainfile.cpp
//
// Created by vinicius on 21/10/2020.
//
#include "Mainfile.h"
#include <cstddef>
#include <cstdio>
Mainfile::Mainfile(char* name, Secondaryfile x)
{
this->name = name;
this->x = x;
}
int Mainfile::getDoubleX(){
return this->x.getX() * 2;
}
Secondaryfile Mainfile::getObj(int num){
return Secondaryfile(num);
}
int main() {
//Test code
printf("Hello World!\n--------\n");
Secondaryfile s = Secondaryfile();
Mainfile f = Mainfile("myname", s);
Secondaryfile myobj = f.getObj(12);
printf("Value = %d", myobj.getX());
}
Mainfile.h
//
// Created by vinicius on 21/10/2020.
//
#ifndef MAINFILE_H
#define MAINFILE_H
#include "Secondaryfile.h"
class Mainfile
{
public:
char* name;
Secondaryfile x;
Mainfile(char*, Secondaryfile);
int getDoubleX();
static Secondaryfile getObj(int);
};
#endif
Mainfile2.cpp
//
// Created by vinicius on 21/10/2020.
//
#include "Secondaryfile.h"
#include "Mainfile2.h"
#include <cstddef>
#include <cstdio>
Secondaryfile Mainfile2::getObj(int num) {
return Secondaryfile(num);
}
int Mainfile2::getDoubleX() {
return this->x.getX() * 2;
}
Mainfile2::Mainfile2(char *name, Secondaryfile x) {
this->name = name;
this->x = x;
}
Mainfile2.h
//
// Created by vinicius on 21/10/2020.
//
#ifndef MAINFILE2_H
#define MAINFILE2_H
class Mainfile2{
public:
char* name;
Secondaryfile x;
Mainfile2(char* name, Secondaryfile x);
int getDoubleX();
static Secondaryfile getObj(int num);
};
#endif
Secondaryfile.cpp
//
// Created by vinicius on 21/10/2020.
//
#include "Secondaryfile.h"
#include <cstddef>
#include <cstdio>
Secondaryfile::Secondaryfile(int x)
{
this->x = x;
}
Secondaryfile::Secondaryfile()
{
this->x = 0;
}
int Secondaryfile::getX()
{
return this->x;
}
int Secondaryfile::add1(int num)
{
return num+1;
}
Secondaryfile.h
//
// Created by vinicius on 21/10/2020.
//
#ifndef SECONDARYFILE_H
#define SECONDARYFILE_H
class Secondaryfile
{
public:
int x;
Secondaryfile();
Secondaryfile(int);
int getX();
static int add1(int);
};
#endif
And the CMakeLists.txt for the project(made in CLion):
cmake_minimum_required(VERSION 3.17)
project(secfile)
set(CMAKE_CXX_STANDARD 14)
include_directories(.)
add_executable(secfile
Mainfile.cpp
Mainfile.h
Mainfile2.cpp
Mainfile2.h
Secondaryfile.cpp
Secondaryfile.h)
After building the project with cmake, you can run it. After doing that, it outputs the following lines:
Hello World!
--------
Value = 12
As expected.
1 https://en.cppreference.com/w/cpp/language/main_function

Related

In function int main(): class name was not declared in this scope

Im using vscode and im new to c++. I learned how to create a header file link to its cpp and use it to main.cpp. The only problem bugs me out is why it causes an error this is my simple code.
Name.h
#include <iostream>
#include <string>
class myname
{
public:
void setname(std::string name);
void prname();
private:
std::string Name;
};
Name.cpp
#include "Name.h"
void myname::setname(std::string name)
{
Name = name;
}
void myname::prname()
{
std::cout<<"Hello :"<<Name<<std::endl;
}
Maiin.cpp
#include <iostream>
#include <string>
#include "Name.h"
using std::cout;
using std::string;
using std::endl;
int main()
{
myname Epoy; // IN FUNCTION INT MAIN: ERROR myname was not declared in this scope
Epoy.setname("Jomar"); //note myname <-rename "BUT THIS IS NOT THE ERROR CAUSE THIS JUST HAPPEN BECAUSE OF THE ERROR ABOVE "
Epoy.prname();
return 0;
}
also i tried so many method i even compiled this by using g++ Maiin.cpp Name.cpp - o Maiin
Still didnt work
Edit: Community want me to add more details.
What I asked was, have you write header guards in your header file: #ifndef Name_H, #define Name_H, #endif ? Since you use vscode you have to done it manually.
Like this:
#ifndef Name_H
#define Name_H
#include <iostream>
#include <string>
class myname
{
public:
void setname(std::string name);
void prname();
private:
std::string Name;
};
#endif
you missing a C++ constructor:
class Foo {
public:
Foo() { /* your init code */ } // <-- this is a std. C++ constructor
~Foo() { /* your clean-up code */ } // <-- this is a std. C++ de-structor
};
int main(int argc, char **argv) {
Foo bar; // here, you don't need the: ( ) object on heap !
}

unable to seperate header classes. I get "does not name a type"

I made a class with a header and a cpp and a main class. When doing so all is good! When separating a class that I will have 2 classes (header+cpp) and one main Class A (Board) does not recognize class B (IllegalCoordinateException) even though I inserted the include. This is probably a newbies question and I might lose some points, but I am stuck in finding my problem.
Here is my working code(stripped down to only the important parts):
main.cpp
#include "Board.h"
#include <iostream>
using namespace std;
int main() {
Board board1{4}; // Initializes a 4x4 board
try {
board1[{3,4}]='O'; // This should raise an exception
} catch (const IllegalCoordinateException& ex) {
cout << "Illegal coordinate" << ex.theCoordinate() << endl; // prints "Illegal coordinate: 3,4"
}
return 0;
}
Board.h
#ifndef CIRC_H
#define CIRC_H
#include <iostream>
#include <string>
using namespace std;
struct coord {
int x;
int y;
};
class IllegalCoordinateException{
coord _coord;
public:
IllegalCoordinateException(coord c){
_coord = c;
}
string theCoordinate() const{
return to_string(_coord.x)+","+to_string(_coord.y);
}
};
class xo{
char x;
public:
char getChar() const{return x;}
char& operator= (const char c){x = c;}
xo& operator= (const xo _xo){
x = _xo.getChar();
return *this;
}
void clear(){
x = '.';
}
operator char() const{
return x;
}
};
class Board{
private:
coord _coord;
xo** board;
int size;
public:
Board();
Board(int v);
~Board();
xo& operator[](coord c); // here is where I use "IllegalCoordinateException"
};
#endif
Board.cpp
#include <iostream>
#include <vector>
#include "Board.h"
using namespace std;
void freeBoard(xo** board,int size){
for(int i = 0 ; i < size ; i++){
delete[] board[i];
}
}
Board::Board()
{
size = 0;
board = new xo* [size];
}
Board::Board(int v)
{
size = v;
board = new xo* [size];
for (int i=0; i<size; i++)
{
board[i] = new xo[size];
for(int j = 0 ; j < size ; j++){
board[i][j].clear();
}
}
}
Board::~Board(){
freeBoard(board,size);
delete[] board;
}
xo& Board::operator[](coord c)
{
if(c.x < size && c.y < size)
{
return board[c.x][c.y];
}
else
{
throw IllegalCoordinateException(c);
}
}
After seperation:
main.cpp
No diff
Board.h also cpp no diff
#ifndef CIRC_H
#define CIRC_H
#include "IllegalCoordinateException.h"
#include <iostream>
#include <string>
using namespace std;
struct coord {
int x;
int y;
};
class xo{
char x;
public:
char getChar() const{return x;}
char& operator= (const char c){x = c;}
xo& operator= (const xo _xo){
x = _xo.getChar();
return *this;
}
void clear(){
x = '.';
}
operator char() const{
return x;
}
};
class Board{
private:
coord _coord;
xo** board;
int size;
public:
Board();
Board(int v);
~Board();
xo& operator[](coord c);
};
#endif
IllegalCoordinateException.h // I also seperated in my code to .h and .cpp (but ofcourse there is no real diff.
#ifndef CIRC_H
#define CIRC_H
#include <iostream>
#include "Board.h"
using namespace std;
class IllegalCoordinateException{
coord _coord;
public:
IllegalCoordinateException(coord c){ _coord = c;}
string theCoordinate() const{return to_string(_coord.x)+","+to_string(_coord.y);}
};
#endif
When doing
$ g++ -g -Og -std=c++0x main.cpp Board.cpp IllegalCoordinateException.cpp
I get:
Board.cpp: In member function ‘xo& Board::operator’:
Board.cpp:60:43: error: ‘IllegalCoordinateException’ was not declared
in this scope
throw IllegalCoordinateException(c);
How can this be? I mean I am including it in the Board.h so Board.cpp is supposed to recognize it!? I tried also to include it in Board.cpp and also make a forward declaration in Board.cpp but both were frugal.
Both of your header files have #ifndef CIRC_H / #define CIRC_H.
So when the first one is included (no matter which order), it defines CIRC_H, and when the second one is included, it gets ignored because the whole file is within #ifndef CIRC_H.
Solution: use a different macro name for each header file.

Getting class type redefinition and a few other errors

I'm creating a student data management console application for a project. I created a class called Student which is storing all the data that a student needs to have, and it also has all the getters and setters associated with it. Here is how all my files are laid out:
Student.h
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
string id;
string email;
int presentation;
int essay1;
int essay2;
int project;
public:
//constructor
//Student();
//setters
void set_name(string);
void set_id(string);
void set_email(string);
void set_presentation(int);
void set_essay1(int);
void set_essay2(int);
void set_project(int);
//getters
string get_name();
string get_id();
string get_email();
int get_presentation();
int get_essay1();
int get_essay2();
int get_project();
};
Student.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
//constructor definition
/*
Student::Student(void) {
cout << "Student created" << endl;
}
*/
//setter definition
void Student::set_name(string s) {
name = s;
}
void Student::set_id(string s) {
id = s;
}
void Student::set_email(string s) {
email = s;
}
void Student::set_presentation(int a) {
presentation = a;
}
void Student::set_essay1(int a) {
essay1 = a;
}
void Student::set_essay2(int a) {
essay2 = a;
}
void Student::set_project(int a) {
project = a;
}
//getter definition
string Student::get_name() {
return name;
}
string Student::get_id() {
return id;
}
string Student::get_email() {
return email;
}
int Student::get_presentation() {
return presentation;
}
int Student::get_essay1() {
return essay1;
}
int Student::get_essay2() {
return essay2;
}
int Student::get_project() {
return project;
}
Main.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
int main() {
cout << "Hello World!" << endl;
Student student1;
Student student2;
Student student3;
student1.set_name("John");
student2.set_name("Bob");
student3.set_name("Carl");
return 0;
}
When I try to run my program, I get, amongst others, the following errors:
Error 1 error C2011: 'Student' : 'class' type redefinition
Error 2 error C2079: 'student1' uses undefined class 'Student'
Error 5 error C2228: left of '.set_name' must have class/struct/union
Error 9 error C2027: use of undefined type 'Student'
How can I go about fixing this issue?
I'm quite sure this is an error caused by the fact that student.h is included twice in a certain .cpp file. Thus you need to use so-called header guards to make sure the file is only included once in every .cpp file:
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
using namespace std;
class Student {
/* ... */
};
#endif
The idea behind this is that an #include is a preprocessor directive that results in the argument file being copied into the file where the #include was issued. Hence, if files A and B include Student.h, and file C includes both files A and B, then the declaration of class Student is going to end up duplicated. Hence the error. The above macros make sure that this doesn't happen.
Edit as per the question author's comment:
#pragma once is the same as #ifndef .. #define #endif but non-standard .
See #pragma once vs include guards? for reference.
I had the same error. I just clean and rebuild the solution and error resolved.

declaring a vector as a class member

I have simple class in a header file: a.hh
#ifndef a_hh
#define a_hh
class a
{
public:
int i;
a()
{
i = 0;
}
};
#endif
Then i have a file:b.cc
#include <iostream>
#include "a.hh"
using namespace std;
int main(int argc, char** argv)
{
a obj;
obj.i = 10;
cout << obj.i << endl;
return 0;
}
>
Till this point everything is fine.
I compile the code and it compiles fine.
But as soon as i add a vector in the class:
#ifndef a_hh
#define a_hh
class a
{
public:
int i;
vector < int > x;
a()
{
i = 0;
}
};
#endif
I get a compilation error as below:
> CC b.cc
"a.hh", line 7: Error: A class template name was expected instead of vector.
1 Error(s) detected.
What is the problem with declaring a vector here as a member?
You need to #include <vector> and use the qualified name std::vector<int> x;:
#ifndef a_hh
#define a_hh
#include <vector>
class a{
public:
int i;
std::vector<int> x;
a() // or using initializer list: a() : i(0) {}
{
i=0;
}
};
#endif
Other points:
(as commented by EitanT) I removed the additional qualification a:: on the constructor
have a read of Why is "using namespace std" considered bad practice?
declaring a vector as a class member:
#include <iostream>
#include <vector>
using namespace std;
class class_object
{
public:
class_object() : vector_class_member() {};
void class_object::add_element(int a)
{
vector_class_member.push_back(a);
}
void class_object::get_element()
{
for(int x=0; x<vector_class_member.size(); x++)
{
cout<<vector_class_member[x]<<" \n";
};
cout<<" \n";
}
private:
vector<int> vector_class_member;
vector<int>::iterator Iter;
};
int main()
{
class_object class_object_instance;
class_object_instance.add_element(3);
class_object_instance.add_element(6);
class_object_instance.add_element(9);
class_object_instance.get_element();
return 0;
}
1.You need to #include <vector> and using namespace std, then a.hh just like below:
#ifndef a_hh
#define a_hh
#include <vector>
using namespace std;
class a
{
public:
int i;
vector <int> x;
a()
{
i = 0;
}
};
#endif
2. If you don't want to only use std namespace in all your code, you can specified the namespace before type, just like std::vector<int> x;

Error While Creating Header Files in C++

There is one header a file Rectangle.hxx
#ifndef Rectangle_included
#define Rectangle_included
#include <iostream>
#include <math.h>
#include "GetL.hxx"
using namespace std;
class Rectangle: public GetL
{
int width;
int value;
public:
Rectangle();
Rectangle(int v, int w);
Rectangle(const Rectangle& b);
int getWidth();
int getValue();
Rectangle & plus(int newval);
};
#endif //Rectangle_included
The file GetL.hxx is defined like this:
#ifndef GetL_included
#define GetL_included
#include <iostream>
using namespace std;
class GetL
{
public:
virtual int getWidth();
};
#endif //GetL_include
The file Rectangle.cxx contains various definitions:
#include <iostream>
#include <math.h>
#include "Rectangle.hxx"
using namespace std;
Rectangle::Rectangle()
{
value=0;
width=0;
}
Rectangle::Rectangle(int v, int w)
{
value=v;
width=w;
}
Rectangle::Rectangle(const Rectangle& b)
{
value= b.value;
width= b.width;
}
int Rectangle::getWidth()
{
return width;
}
int Rectangle::getValue()
{
return value;
}
Rectangle& Rectangle::plus(int newval)
{
value+=newval;
if(value>=pow(2,width))
cout<<"Overflow";
return *this;
}
But i am getting the error on compiling Rectangle.cxx.
/tmp/cclETn3R.o:Rectangle.cxx:(.text$_ZN4GetLC2Ev[GetL::GetL()]+0*8): undefined reference to 'vtable for Getl'
How can i remove it? How can i define file GetL.cxx or i don't need to?
You need to compile the different files without linking first. On UNIX compilers this is typically done using the -c option. When building the executable you then specify all the produced .o objects. Alternatively you can specify all source files at once but this is really only viable for very small projects.
You must implement GetL::getWidth(). Given your other files, you will probably implement it in GetL.cxx.