I have to class that use each other but whatever I tried I couldn't achieve to make them work.
I just want them to access each other and after days of struggle, I decided to ask here.
If someone can point out what I am doing wrong and what I should do instead it would be great.
Edit: I decided to implement one of the solutions which are already on stack overflow and changed my code according to that:
I will also share errors this time so maybe we can figure out what's wrong.
I tried to copy this:
Resolve build errors due to circular dependency amongst classes
I used class name "Unit" instead of "A" and "Skill" instead of
"B"
Skill.h
#pragma once
#include <iostream>
#include <vector>
#include "Unit.h"
using namespace std;
class Skill :
public Unit
{
double _val;
Unit* unitPtr;
public:
Skill(double val):_val(val)
{
}
void SetSkill(Unit* unit)
{
unitPtr = unit;
unitPtr->Print();
}
void Print()
{
cout << "Type:B val=" << _val << endl;
}
// Unit* unitPtr;
vector <Skill *> attacks;
vector <Skill *> utilities;
vector <Skill *> movement;
};
Unit.h
#pragma once
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Skill;
class Unit
{
int _val;
Skill* skillPtr;
public:
Unit(int val) :_val(val)
{
stunned = false;
curSpeed = speed + rand() % 8 + 1;
}
void SetSkill(Skill* skill)
{
skillPtr = skill;
skillPtr->Print(); // COMPILER ERROR: C2027: use of undefined type 'B'
}
void Print()
{
cout << "Type:A val=" << _val << endl;
}
int GetDodge()
{
return dodge;
}
void Setup();
string name;
int maxHP;
//... and other variables
};
Unit.cmp
#include "Skill.h"
#include "Unit.h"
void Unit::Setup()
{
heroes.push_back(new Vestal);
heroes.push_back(new Vestal);
heroes.push_back(new Crusader);
heroes.push_back(new Crusader);
monsters.push_back(new BoneSoldier);
monsters.push_back(new BoneDefender);
monsters.push_back(new BoneSoldier);
monsters.push_back(new BoneDefender);
}
Later on the code, I add some stuff to attacks, utilities, and moment and I want to access them from the Unit object, like below:
heroes[0]->skillPtr->attacks[0]
And I want to be able to access the variables in the Unit.h (like maxHP) from Skill.h
Errors:
Error C2512 'Skill': no appropriate default constructor available
Error C2512 'Unit': no appropriate default constructor available
I'm a beginner but maybe I can see a couple of issues that are likely causing you problems here.
First you've got a classic circular dependency here, Unit.h includes Skill.h which includes Unit.h which includes Skill.h and so on.
Secondly not seeing any #pragma once pre-proccessor directives. Which means when you then go on to try and include both Skill.h and Unit.h in your unit CPP file, you will try to include the .h files more than once, as they include each other...
Thirdly you're using namespace std in the global scope. You can do that, but don't do that.
If you're looking for more try this excellent video on the subject
https://www.youtube.com/watch?v=Zbw58vTotok
Related
new to this site and also C++ but hoping to see some guidance from everyone.
I had a pretty fun project idea to learn C++ digging deeper with APIs, classes, references, etc. and currently I have a working example of code where everything exist within the main.cpp file. The issue I am facing is that when i move the classes (inner and outer) to their own respective header files the code no longer compiles.
The reason for the nested classes is that the OuterAPI serves as the main entry point to the API and has many lower level APIs that can be then accessed beneath it (people, licenes, roles, etc). This way users of API would only have to create an object for the OuterAPI and then dot notation for underlying resource and method.
Here is the working example in the main.cpp
#include <iostream>
#include <nlohmann/json.hpp>
#include <cpr/cpr.h>
using json = nlohmann::json;
class OuterAPI {
private:
class InnerAPI {
private:
OuterAPI& api;
public:
InnerAPI(OuterAPI& a) :api(a) {}
json get() {
cpr::Response r = cpr::Get(
cpr::Url{ api.baseUrl + "resource" },
cpr::Bearer{ api.token }
);
return json::parse(r.text)
};
std::string token;
std::string baseUrl = "";
public:
InnerAPI people;
OuterAPI(std::string t) : token(t), people(*this) {}
};
int main(int argc, char** argv)
{
std::string token = "";
OuterAPI api(token);
json jsonData = api.people.get();
std::cout << jsonData.dump(4) << std::endl;
return 0;
}
Here is me moving everything to respective header/cpp files
OuterAPI.h
#pragma once
class OuterAPI {
private:
class InnerAPI;
std::string token;
std::string baseUrl = "";
public:
OuterAPI(std::string t);
~OuterAPI();
InnerAPI* people;
};
OuterAPI.cpp
#include "WebexAPI.h"
#include "PeopleAPI.h"
OuterAPI::OuterAPI(std::string t) : token(t) {
people = new InnerAPI(*this);
}
OuterAPI::~OuterAPI() { delete people; }
InnerAPI.h
#pragma once
#include <nlohmann/json.hpp>
#include <cpr/cpr.h>
#include "OuterAPI.h"
using json = nlohmann::json;
class OuterAPI::InnerAPI {
private:
OuterAPI& api;
public:
InnerAPI(OuterAPI& a);
json get();
};
InnerAPI.cpp
#include "InnerAPI.h"
OuterAPI::InnerAPI::InnerAPI(OuterAPI& a) : api(a) {}
json OuterAPI::InnerAPI::get() {
cpr::Response r = cpr::Get(
cpr::Url{ api.baseUrl + "resource" },
cpr::Bearer{ api.token }
);
return json::parse(r.text);
main.cpp (finally) - this is where the compiler error occurs at api.people.get() "expression must have class type but has type "OuterAPI::InnerAPI *"
int main(int argc, char** argv)
{
std::string token = "";
OuterAPI api(token);
json jsonData = api.people.get(); // COMPILER ERROR "expression must have class type but has type "OuterAPI::InnerAPI *"
std::cout << jsonData.dump(4) << std::endl;
return 0;
}
From this I believe the issue is associated with me having to define the InnerAPI object people as a pointer inside of OuterAPI but from here I cant seem to come to a resolution.
Also, feel free to critique my design as well, like I say I am new to C++ so want to make sure I can do a good job. Thanks.
In OuterAPI* you have declared people as a member of type InnerAPI*.
You can either call your API using api.people->get() or make the member a InnerAPI instead.
EDIT:
It seems the error, besides the pointer thing, comes from how you handle file includes. I managed to get a working version on REPL.it. I made slight adjustments so I wouldn't have to bring both libraries in so focus on the gist of it. Here it is:
OuterAPI.h
#pragma once
#include <string>
class OuterAPI {
private:
class InnerAPI;
std::string token;
std::string baseUrl = "";
public:
OuterAPI(std::string t);
~OuterAPI();
InnerAPI* people;
};
InnerAPI.j
#pragma once
#include "./OuterAPI.h"
class OuterAPI::InnerAPI {
private:
OuterAPI& api;
public:
InnerAPI(OuterAPI& a);
std::string get();
};
OuterAPI.cpp
#include "./OuterAPI.h"
#include "./InnerAPI.h"
OuterAPI::OuterAPI(std::string t) : token(t) {
people = new InnerAPI(*this);
}
OuterAPI::~OuterAPI() { delete people; }
InnerAPI.cpp
#include "./OuterAPI.h"
#include "./InnerAPI.h"
OuterAPI::InnerAPI::InnerAPI(OuterAPI& a) : api(a) {}
std::string OuterAPI::InnerAPI::get() {
return api.baseUrl + "resource";
}
Make sure you include everything you intend to use in every file where you intend to do so.
Separating declaration and definition is pretty common.
It's a way to reduce compile time on large projects.
Thankfully modules will soon™ make linking a thing of the past.
To address the error message: you declare people as a raw member pointer of the class OuterAPI… You cannot access a member through a pointer using operator ., you need to use operator ->.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 2 years ago.
I'm getting undefined reference errors. Can you please figure out why?
Errors:
undefined reference to Breuken::Breuken(int, int)
undefined reference to Breuken::som()
(I'm kinda new in c++ programming. I am currently working on a project now, using header files another source file and main source file.)
Here is my code:
Header File (Breuk.H):
using namespace std;
class Breuken{
Breuken(int, int);
void som();
void setTeller1(int);
void setNoemer1(int);
int getTeller1();
int getNoemer1();
private:
int teller1;
int noemer1;
};
Source File(Breuk.cpp):
#include <iostream>
#include "Breuk.h"
using namespace std;
Breuken::Breuken(int tel1, int noem1)
{
setTeller1(tel1);
setNoemer1(noem1);
}
int Breuken::getTeller1()
{
return teller1;
}
int Breuken::getNoemer1()
{
return noemer1;
}
void Breuken::setTeller1(int tel1)
{
teller1 = tel1;
}
void Breuken::setNoemer1(int noem1)
{
noemer1 = noem1;
}
int Breuken::som()
{
cout<<"Breuken zijn: "<<getTeller1()<<" / "<<getNoemer1()<<endl;
}
main file(main.cpp):
#include <iostream>
#include "Breuk.h"
using namespace std;
int main()
{
Breuken br(1, 2);
br.som();
return 1;
}
If I got this right, you want to use a class, but the only thing you did is declare some functions without actually defining them.
What you need to do is put everything in your header inside a class like that:
class Breuk {
private:
int teller1;
int noemer1;
public:
Breuk(int tel1, int noem1);
void som();
void setTeller1(int tel1);
void setNoemer1(int noem1);
int getTeller1();
int getNoemer1();
};
Also, don't forget to give the variables inside the function head a name!
The .cpp file you need to get the reference to the class right (the part before the ::). It has to be the same name as your class. Also, it's not so great to use setter inside the constructor. It's better to reference the member variables directly (the variables inside the class). In order to do that you need to use "this->variable". "this" will refer to the current class you're in. That means if you write this->teller1 it will refer to the variable teller1 inside the class.
#include <iostream>
#include "Breuk.hpp"
using namespace std;
Breuk::Breuk(int tel1, int noem1)
{
// setTeller1(tel1); theoreticly ok but its better to access
// setNoemer1(noem1); member variables (variables inside a class) directly
this->teller1 = tel1;
this->noemer1 = noem1;
}
int Breuk::getTeller1()
{
return teller1;
}
int Breuk::getNoemer1()
{
return noemer1;
}
void Breuk::setTeller1(int tel1)
{
teller1 = tel1;
}
void Breuk::setNoemer1(int noem1)
{
noemer1 = noem1;
}
void Breuk::som()
{
cout << "Breuken zijn: " << getTeller1() << " / " << getNoemer1() << endl;
}
in the main.cpp you only made a small mistake with the return 0 and the name of the class.
#include "Breuk.hpp"
using namespace std;
int main()
{
Breuk br(1, 2); // make sure u use the same name your class has
br.som();
return 0; // return 0 at the end: it means that the program executed correctly
// return 1 would mean that an error occured
}
Also, I suggest using .hpp files instead of .h files. There is no real difference but it's more common to use .hpp for c++.
I'm making a car design program. For this program, we are making a class in a header file, and then we will use that header file in our main program by including the file using #include "name of header".
This is my professors header. This is the code in his header. We were instructed to do the header like he is.
/*
Program 14-2
author - Ray Warren, modified from Language Companion
last updated - 19 July 2013
*/
#include <string>
using namespace std;
class CellPhone
{
private:
// Field declarations
string manufacturer;
string modelNumber;
double retailPrice;
public:
// Constructor
CellPhone(string manufact, string modNum, double retail)
{
manufacturer = manufact;
modelNumber = modNum;
retailPrice = retail;
}
// Member functions
void setManufacturer(string manufact)
{
manufacturer = manufact;
}
void setModelNumber(string modNum)
{
modelNumber = modNum;
}
void setRetailPrice(double retail)
{
retailPrice = retail;
}
string getManufacturer()
{
return manufacturer;
}
string getModelNumber()
{
return modelNumber;
}
double getRetailPrice()
{
return retailPrice;
}
}; //end class
This is the program he used the header file in (as you see he included the header file).
/*
Program14-2
author - Ray Warren, modified from Language Companion
last updated - 19 July 2013
*/
#include <iostream>
#include <cstdlib>
#include "CellPhone.hpp"
using namespace std;
int main()
{
// Create a CellPhone object and initialize its
// fields with values passed to the constructor.
CellPhone myPhone("Motorola", "M1000", 199.99);
// Display the values stored in the fields.
cout << "The manufacturer is "
<< myPhone.getManufacturer() << endl;
cout << "The model number is "
<< myPhone.getModelNumber() << endl;
cout << "The retail price is "
<< myPhone.getRetailPrice() << endl;
system("Pause");
return 0;
} //end main
This is my header file containing my class.
#include <string>
using namespace std;
Car(int ym, string mk)
{
yearModel=ym;
make=mk;
speed=0;
}
void setYearModel(int ym)
{
yearModel=ym;
}
void setMake (string mk)
{
make=mk;
}
int returnYearModel()
{
return yearModel;
}
string returnMake()
{
return make;
}
int returnSpeed()
{
return speed;
}
void accelerate()
{
speed += 5;
}
void brake()
{
This is my main program with me attempting to include the header file into my main program. When I tried to compile this, my header file popped up in a new code blocks IDE tab, and gave me this list of errors.
http://prntscr.com/bzu4x5 <--------- list of errors
I have no idea what I'm doing wrong. From what I see, I copied my professor exactly as he told us to, and I'm still getting errors.
Does anyone have any ideas of what's causing this massive list of errors?
#include <string>
#include <iostream>
#include "Car header.h"
int main()
{
}
Your "header file" contains the definitions of the class member functions. It should actually be a .cpp file. What you are missing is a definition of the class itself, and declarations of the member functions.
Note that your professor's sample header file defines the member functions inside the class definition. This is actually poor practise, but he may not have got round to teaching you how do define functions out of line yet.
If you are going to define the functions out of line, you will also need to change the functions to some thing like:
std::string Car::returnMake()
{
return make;
}
Note: "using namespace std" is also poor practise. Professional C++ code tends to be explicit, and use the "std::" prefix. Just get in the habit and save yourself hours of pain.
You did not actually define a class in you header file. Notice that in your teacher's header file, he has:
class Cellphone // -> this is what you do not have
{
private:
// Field declarations
string manufacturer;
string modelNumber;
double retailPrice;
public:
//constructor function
CellPhone(string manufact, string modNum, double retail);
// Member functions
void setManufacturer(string manufact);
void setModelNumber(string modNum);
void setRetailPrice(double retail);
string getManufacturer();
string getModelNumber();
double getRetailPrice();
}
You should have you fields and member functions inside your class. Hope that helps
I have the following files:
ListaEnc.hpp
#include "Elemento.hpp"
#include <cstdlib>
#include <iostream>
template<typename T>
class ListaEnc {
public:
ListaEnc();
~ListaEnc();
...
}
//Implementation:
template<typename T>
ListaEnc<T>::ListaEnc()
{
head = NULL;
size = 0;
}
template <class T>
ListaEnc<T>::~ListaEnc() {
}
main.cpp:
#include "ListaEnc.hpp"
using namespace std;
int main(int argc, char** argv)
{
ListaEnc<int>* teste = new ListaEnc<int>();
return 0;
}
Poligono.hpp
#ifndef POLIGONO_HPP
#define POLIGONO_HPP
#include "Ponto.hpp"
#include "ListaEnc.hpp"
#include <string>
using namespace std;
public:
//Construtores
Poligono(ListaEnc<Ponto> pontos, string nome);
Poligono(const Poligono& orig);
virtual ~Poligono();
//Metodos
string obterNome();
void adicionarPonto(Ponto);
ListaEnc<Ponto> obterPontos();
private:
ListaEnc<Ponto> pontos;
string nome;
};
#endif /* POLIGONO_HPP */
Poligono.cpp
#include "Poligono.hpp"
* Poligono::Poligono(ListaEnc<Ponto> pontos, string nome)
{
this->pontos = pontos;
this->nome = nome;
}
* Poligono::Poligono(const Poligono& orig) {
}
* Poligono::~Poligono() {
}
//Metodo
string Poligono::obterNome()
{
return this->nome;
}
ListaEnc<Ponto> Poligono::obterPontos()
{
return this->pontos;
}
void Poligono::adicionarPonto(Ponto p)
{
this->pontos.adiciona(p);
}
I get these compile errors on Poligono.cpp:
/home/mariana/NetBeansProjects/TrabalhoCG/Poligono.cpp:12: undefined reference to `ListaEnc::~ListaEnc()'
The destructor for ListaEnc is empty, but is implemented. Does anyone know how to solve this problem?
Edit: Added the implementation of constructor and destructor for ListaEnc. The error appears in the bit of code I added for Poligono.cpp, where ListaEnc is one of the parameters.
Edit2: I have added an asterisk to the points in Poligono.cpp where the error appears (The first constructor, second constructor and destructor)
Since you posted code that shows
#ifndef POLIGONO_HPP
#define POLIGONO_HPP
in Poligono.cpp, but you don't have the same in ListaEnc.hpp, I assume that you are missing include guards in that header?
Depending on what other code is included in Poligono.cpp, this could result in the definition of template ListaEnc twice. Under C++ standard if you break the one definition rule you may just get a linking error and no other diagnostic message.
So, maybe make sure that there are include guards in ListaEnc.hpp ?
If you post more code I will update this answer :)
Edit: Another suggestion, if it is having trouble finding the dtor definition of ListaEnc, you might try moving the implementation of it into the class body? This makes it less likely that a typo will cause it to be lost. Since all the code is in the header this really doesn't change anything otherwise.
Hello I am new to using header files and OPP in my programs and I am wondering why visual studio 2010 is stating that there are errors in my code. The code compiles and runs as desired but there are red lines under all of the objects
here is the header file
//functions.h
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <string>
using namespace std;
class vehicle
{
public:
int hp;
int ammo;
void displayHP();
void displayAmmo();
void displayName();
string vesselName;
void setName(string);
void moveUP(int& y);
void moveDown(int& y);
void moveLeft(int &x);
void moveRight(int &x);
private:
};
//implementation section
void vehicle::displayHP(){cout<<hp<<endl;}
void vehicle::displayAmmo(){cout<<ammo<<endl;}
void vehicle::setName(string name){vesselName=name;}
void vehicle::displayName(){cout<<vesselName<<endl;}
void vehicle::moveUP(int& y)
{
y=y-1;//moves boat up
system("cls");
}
void vehicle::moveDown(int& y)
{
y=y+1;//moves boat down
system("cls");
}
void vehicle::moveLeft(int &x)
{
x=x-1;// moves the boat left
system("cls");
}
void vehicle::moveRight(int &x)
{
x=x+1;//moves boat right
system("cls");
}
void moveBoat(int &x,int& y, int a,int b,int s,int turn)
{
here is the header file that contains the boats movements. The program compiles fine and works as designed but I was confused why visual studio is claiming there are so many errors I added line comments to where the errors in the boat.h file
//boat.h
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <string>
#include "functions.h"
using namespace std;
void moveBoat(int &x,int& y, int,int,int,int);
void youScrewedUp(int &x,int& y, int,int,int,int);
int movement=0;
vehicle destroyer;
destroyer.hp=500;//<==== getting a red line under the word destroyer error says "this deceleration has no storage class or type specifier"
destroyer.ammo=500;//<==== getting a red line under the word destroyer error says "this deceleration has no storage class or type specifier"
displayArray(x,y,a,b,s);//<===="this deceleration has no storage class or type specifer"
destroyer.setName("USS YAY I LEARNED CLASSES");//<===="this deceleration has no storage class or type specifer"
destroyer.displayName();//<===="this deceleration has no storage class or type specifer"
destroyer.displayHP();//<===="this deceleration has no storage class or type specifer"
cout<<"Boat Location X "<<x<<" Y "<<y<<endl;
if(s==1)
{
cout<<"ENEMY SHIP SIGHTED"<<endl;//<===="this deceleration has no storage class or type specifer"
}
cout<<"1.move left"<<endl;//<===="this deceleration has no storage class or type specifer"
cout<<"2.move right"<<endl;//<===="this deceleration has no storage class or type specifer"
cout<<"3.move up"<<endl;//<===="this deceleration has no storage class or type specifer"
cout<<"4.move down"<<endl;//<===="this deceleration has no storage class or type specifer"
cin>>movement;<===="this deceleration has no storage class or type specifer"
switch(movement)//<==expected a deceleration
{
case 1:
if(x>0)//does not allow boat to leave grid
{
destroyer.moveLeft(x);
}
else
{
youScrewedUp(x,y,turn,a,b,s);// function that repeats the movement function and displays a message
}
break;
case 2:
if(x<9)//boundary
{
destroyer.moveRight(x);
}
else
{
youScrewedUp(x,y,turn,a,b,s);
}
break;
case 3:
if(y>0)//boundary
{
destroyer.moveUP(y);
}
else
{
youScrewedUp(x,y,turn,a,b,s);
}
break;
case 4:
if(y<9)//boundary
{
destroyer.moveDown(y);
}
else
{
youScrewedUp(x,y,turn,a,b,s);
}
break;
}
turn++;//adds one to the turn counter to cycle to the enemies turn
}
void youScrewedUp(int &x, int &y,int turn, int a, int b,int s)// must pass the x y values by refferance
{
cout<<"where are you going your leaving the battlefield"<<endl;
cout<<"please make another selection"<<endl;
system("pause");
system("cls");
moveBoat(x,y,turn,a,b,s);
}
Here is my main()
// arrayTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "array.h"
#include "boat.h"
#include "enemy.h"
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int turn=1;// turn counter cycles between 1 and 2 during player and enemy turns
int x=7;//x coordinate for destroyer
int y=6;//y coordinate for destroyer
int a=3;//x coordinate for sub
int b=4;//y coordinate for sub
int s=0;//toggle for submerged or not chose not to use a bool because I used a random number generator to allow a 25% chance opposed to a 50% chance
srand (time(NULL));
do{
moveBoat(x,y,turn,a,b,s);//function that moves the boat
moveEnemy(a,b,turn,x,y,s);//function to move the enemy
}while(turn<3);// this is temporary will be replaced when a hp and weapons system is completed
system("pause");
return 0;
}
This goes beyond your base question and adds some other things that will improve your code and hopefully understanding.
You need to put your 'main' function code literally in a main function
int main(int argc, char * argv[])
{
//do stuff here....
return 0;
}
You should include header guards to prevent you from including 'function.h' multiple times. I would also strongly suggest renaming it to Vehicle.h to be emblematic of the class it is providing.
#ifndef __VEHICLE_H__
#define __VEHICLE_H__
//... all the good stuff.
#endif
I would STRONGLY suggest you remove using namespace std from your header file as doing so will trash the namespaces of anyone who wishes to use your header. Instead simply use std:: where needed or if you really don't want to use them everywhere, consider doing a using std::xyz; for the specific features you are using. This way at least you can trace down collisions later. If you want to do this in an implementation file (i.e. *.c) that's up to you; but don't do it in files that are included generally speaking.
Don't include headers you aren't using in your header file. This is a bad habit, leads to code and compiler bloat, and will inevitably cause pain later. You shouldn't be including ctime or stdafx in each of your headers as they don't refer to it.
You need to put the body of 'stuff' that is floating inside boat.h into a function
//somefunct
void somefunction()
{
int movement=0;
vehicle destroyer;
destroyer.hp=500;//<==== getting a red line under the word destroyer error says "this deceleration has no storage class or type specifier"
destroyer.ammo=500;//<==== getting a red line under the word destroyer error says "this deceleration has no storage class or type specifier"
//.... Everything else
}