problem with constructors and g++ compile recipe - c++

I'm creating a cpp program using functions that are applied to C++11. Even though the code seems correct and has no syntax errors i'm getting this message when i compile:
/tmp/cce9dpew.o: In function `Object::Object()':
classes.cpp:(.text+0xd): undefined reference to `vtable for Object'
/tmp/cce9dpew.o: In function `Object::~Object()':
classes.cpp:(.text+0x45): undefined reference to `vtable for Object'
/tmp/cce9dpew.o:(.rodata._ZTI6String[_ZTI6String]+0x10): undefined reference to `typeinfo for Object'
collect2: error: ld returned 1 exit status
I have to add here that if i put all those .cpp and .h files in one it runs Aok printing constructor and destructor cout's just fine.
Can someone help?The code is below.
compile recipe i used to run them all together: g++ -std=c++0x classes.h classes.cpp mainiz.cpp
classes.h:
#ifndef CLASSES_H
#define CLASSES_H
#include <iostream>
#include <cstring>
using namespace std;
class Object
{
private:
int id;
public:
Object();
~Object();
void set_id(int ids);
int get_id();
void Equal(Object* bj) const;
void Identical(Object* bj) const;
virtual Object* clone();
virtual void toString();
};
class String:public Object
{
string characters;
public:
String();
~String();
void set_char(string a);
string get_char();
String* clone();
void toString();
int Length();
void Clear(string a);
string& Concat(string &a);
char At(char b);
string& UpdateAt(string a,string charact);
void Print(const string a) const;
};
#endif //CLASSES_H
classes.cpp:
#include <iostream>
#include <cstring>
#include "classes.h"
using namespace std;
//FOR OBJECT CLASS
Object::Object(){ cout << "An object just got created." << endl;}
Object::~Object(){ cout << "An object just got destroyed." << endl; }
void Object::set_id(int ids) { this->id = ids; }
int Object::get_id() { return this->id;}
void Object::Equal(Object* bj) const
{
if((this->id == bj->id))
{
cout << "The objects are equal." << endl;
}
else
{
cout << "The objects are not equal." <<endl;
}
}
void Object::Identical(Object* bj) const
{
if(this==bj)
{
cout << "The objects are identical." <<endl;
}
else
{
cout << "The objects are not identical." <<endl;
}
}
//FOR STRING CLASS
String::String(){ cout << "String just created" << endl;}
String::~String(){ cout << "String to be destroyed" << endl;}
void String::set_char(string a) { this->characters = a;}
string String::get_char() { return this->characters;}
String* String::clone() { return this;}
void String::toString() {cout << "characters" << endl;}
int String::Length()
{
string a = this->characters;
return a.length();
}
void String::Clear(string a)
{
this->characters.clear();
}
string& String::Concat(string &a){ return (this->characters.append(a));}
char String::At(char b) { return (this->characters.find(b)); }
string& String::UpdateAt(string a,string charact)
{
int position=this->characters.find(charact);
return this->characters.replace(position,1,a);
}
void String::Print(const string a) const { cout << "print of string:" << a << endl; }
mainiz.cpp:
#include <iostream>
#include <cstring>
#include "classes.h"
using namespace std;
int main()
{
Object k;
Object *st = new String;
String d;
}

Making the destructor for Object class "virtual" you would get another error for undefined reference to Object::clone and Object::toString.
You can try what #Igor suggested, but your current mainiz.cpp code won't work because C++ doesn't allow an instance of a class with pure virtual methods.
You can try the following code:
class Object {
virtual ~Object();
virtual Object* clone();
virtual void toString();
};
Object* Object::clone() {
// Make your implementation here
return nullptr;
}
void Object::toString() {
// Make your implementation here
}

Object::clone and Object::toString are declared but never implemented.
If you want to leave them unimplemented, make them pure virtual, as in
class Object {
virtual Object* clone() = 0;
};

None of the solutions given above were correct.The problem was within my compilation recipe.These functions started existing after C++11 so if you're using something like that your compilation recipe should be:
g++ -g -std=c++11 -o executable file.cpp main.cpp

Related

bind class member funtion to std::function not need check parameters?

why gcc 9.4 not check parameters when bind a class member funtion to a std::function viriable, but check when bind a global function? here is example code, CreateRpcFun has a parameter, but Test member function print doesn't have any other parameters except this, bind print to CreateRpcFun works well, but global funtion print2 cannot, can anybody explain why?
#include <functional>
#include <iostream>
#include <string>
using namespace std;
using CreateRpcFun = std::function<void(const string &)>;
class Test {
public:
Test() : str_("nihao!") {}
// bind print to CreateRpcFun passed compile
void print() { cout << str_ << endl; }
private:
string str_;
};
class Holder {
public:
CreateRpcFun CreateRpc;
};
class Other {
public:
Other(Holder h, string str) : h_(h), str_(str) {}
void run() { h_.CreateRpc("world!"); }
private:
Holder h_;
string str_;
};
void print1(const string &str) { cout << str << endl; }
void print2() { cout << "magic" << endl; }
int main() {
Test t;
Holder h;
h.CreateRpc = std::bind(&Test::print, &t);
Other o(h, "hhhh");
o.run();
h.CreateRpc = &print1;
h.CreateRpc("test");
// h.CreateRpc = &print2; // compile error
// h.CreateRpc("test");
}

Trying to access variables from another class

Im having an issue getting my variable from my original class to print in another class method
Quick example of my issue:
say the variable was declared here in the test.h file:
class player{
private:
int x = 10;
void setX(); //method for setting X from user input
int getX(); //Method for retrieving variable
}
Then in another class method where i want to print X
class inTheWoods{
public:
printInfo();
}
test.cpp file:
void player::setX(){
cout << "Set X to a number:" << endl;
cin >> x
}
int player::getX(){
return x;
}
int inTheWoods::printInfo(){
player playerObj; //Player object to access methods in player class
cout << playerObj.getX();
}
main.cpp:
int main(){
inTheWoods woodsObj;
woodsObj.printInfo();
return 0;
}
Whenever I run my program that resembles this problem the int does not display correctly and throws me a strange negative number. I hope this isnt too much code and that I documented everything correctly
If you want the classes to be in a separate files, it should still work:
Main.cpp
#include <iostream>
#include "inTheWoods.h"
int main()
{
inTheWoods woodsObj;
woodsObj.printInfo();
return 0;
}
Player.h
#pragma once
#include <iostream>
class Player
{
int x = 10;
void setX();
public:
int getX();
};
Player.cpp
#include "Player.h"
void Player::setX()
{
std::cout << "Set X to a number:" << std::endl;
std::cin >> x;
}
int Player::getX()
{
return x;
}
inTheWoods.h
//#pragma once
#include "Player.h"
#include <iostream>
class inTheWoods
{
public:
void printInfo();
};
inTheWoods.cpp
#include "inTheWoods.h"
void inTheWoods::printInfo()
{
Player playerObj; //Player object to access methods in player class
std::cout << playerObj.getX();
}
#pragma once is a preprocessor that prevents multiple includes, in case you didn't know. You can choose to skip it (Visual Studio auto-generated the file with the line).
In summary, these are the changes I needed to make from your implementation:
Move declaration of getX() from private to public.
Add semicolons to the end of every class.
Add a return type to printInfo(). If you don't want a function to return anything, the return type is void. Unless you care declaring a constructor, which doesn't seem to be the case here.
Here is the working one. It's always a good practice to give a constructor, in order to create an instance with some default values. the following code will work hopefully according to your requirements:
main.cpp
#include <iostream>
#include "inTheWoods.h"
int main()
{
inTheWoods woodsObj;
woodsObj.printInfo();
return 0;
}
player.h
#pragma once
class player
{
private:
int m_x;
public:
player();
player(const int& x);
void setX(); //method for setting X from user input
const int& getX()const; //Method for retrieving variable
};
player.cpp
#include "player.h"
#include <iostream>
player::player() // defualt constructor
:m_x(0) {}
player::player(const int& x)
:m_x(x) {} // parameterised
void player::setX()
{
std::cout << "Set X to a number:" << std::endl;
std::cin >> m_x;
}
const int& player::getX()const
{
return m_x;
}
inTheWoods.h
#pragma once
class inTheWoods
{
public:
inTheWoods();
~inTheWoods();
void printInfo();
};
inTheWoods.cpp
#include "inTheWoods.h"
#include "player.h"
#include <iostream>
inTheWoods::inTheWoods() {}
inTheWoods::~inTheWoods() {}
void inTheWoods::printInfo()
{
//Player object to access methods in player class
player playerObj; // will beinitialized with 0
player playerObj2(10); // will beinitialized with 10
std::cout << playerObj.getX() <<std::endl;
std::cout << playerObj2.getX() <<std::endl;
}
Edit: Well if you wanna allow the user to set values your printInfo() must be as follows:
void inTheWoods::printInfo()
{
//Player object to access methods in player class
player playerObj; // will beinitialized with 0
playerObj.setX();
std::cout << playerObj.getX() <<std::endl;
}

Declaration is incompatible with type

header file:
#ifndef H_bankAccount;
#define H_bankAccount;
class bankAccount
{
public:
string getAcctOwnersName() const;
int getAcctNum() const;
double getBalance() const;
virtual void print() const;
void setAcctOwnersName(string);
void setAcctNum(int);
void setBalance(double);
virtual void deposit(double)=0;
virtual void withdraw(double)=0;
virtual void getMonthlyStatement()=0;
virtual void writeCheck() = 0;
private:
string acctOwnersName;
int acctNum;
double acctBalance;
};
#endif
cpp file:
#include "bankAccount.h"
#include <string>
#include <iostream>
using std::string;
string bankAccount::getAcctOwnersName() const
{
return acctOwnersName;
}
int bankAccount::getAcctNum() const
{
return acctNum;
}
double bankAccount::getBalance() const
{
return acctBalance;
}
void bankAccount::setAcctOwnersName(string name)
{
acctOwnersName=name;
}
void bankAccount::setAcctNum(int num)
{
acctNum=num;
}
void bankAccount::setBalance(double b)
{
acctBalance=b;
}
void bankAccount::print() const
{
std::cout << "Name on Account: " << getAcctOwnersName() << std::endl;
std::cout << "Account Id: " << getAcctNum() << std::endl;
std::cout << "Balance: " << getBalance() << std::endl;
}
Please help i get an error under getAcctOwnersName, and setAcctOwnersName stating that the declaration is incompatible with "< error-type > bankAccount::getAcctOwnersName() const".
You need to
#include <string>
in your bankAccount header file, and refer to the strings as std::string.
#ifndef H_bankAccount;
#define H_bankAccount;
#include <string>
class bankAccount
{
public:
std::string getAcctOwnersName() const;
....
once it is included in the header, you no longer need to include it in the implementation file.
I've found that when a private member variable and a member function have the same name the IDE gives me the "incompatible" error, perhaps that is what you are experiencing...
Sometimes this error occur because it's vary from machine to machine. Your program will work fine if you declare your class and all of its implementations in one file instead doing declaration of class in other file and linked it with your driver file.
Again: This is totally machine dependent error.
In visual studio 2012 you will face this kind of error because it not work for these files while in other versions of vs you will not face any error type exception.
Hope it's worth.....

Trouble with abstract classes in c++

main:
#include <iostream>
#include <string>
#include "serviceChargeChecking.h"
int main()
{
serviceChargeChecking newAccount("Crim", 111222, 50.00, 100, 1.00);
system("PAUSE");
return 0;
}
serviceChargeChecking.h:
#ifndef H_serviceChargeChecking
#define H_serviceChargeChecking
#include "checkingaccount.h"
#include <string>
class serviceChargeChecking: public checkingAccount
{
public:
void setMonthlyFee(double);
void writeCheck(int);
void getMonthlyStatement() const;
serviceChargeChecking(std::string =" ",int = 0, double = 0.00, int= 0, double = 0.00);
private:
double serviceCharge;
};
#endif
serviceChargeChecking.cpp:
#include "serviceChargeChecking.h"
#include <iostream>
using std::string;
void serviceChargeChecking::setMonthlyFee(double fee)
{
serviceCharge=fee;
}
void serviceChargeChecking::getMonthlyStatement() const
{
checkingAccount::getMonthlyStatement();
std::cout<< "Service Charge: " << serviceCharge << std::endl;
}
void serviceChargeChecking::writeCheck(int ammount)
{
if(checkingAccount::getChecks()>0)
{
checkingAccount::setChecks(checkingAccount::getChecks()-ammount);
}
else
{
std::cout<<"No checks available." << std::endl;
}
}
serviceChargeChecking::serviceChargeChecking(string name, int acct, double bal, int numCheck, double sCharge)
{
bankAccount::setAcctOwnersName(name);
bankAccount::setAcctNum(acct);
bankAccount::setBalance(bal);
checkingAccount::setChecks(numCheck);
serviceCharge=sCharge;
}
checkingAccount.h:
#ifndef H_checkingAccount
#define H_checkingAccount
#include "bankAccount.h"
#include <iostream>
class checkingAccount: public bankAccount
{
public:
virtual void writeCheck()=0;
void deposit(double);
void withdraw(double);
void getMonthlyStatement() const;
int getChecks();
void setChecks(int);
private:
int numChecks;
};
#endif
checkingAccount.cpp:
#include "checkingAccount.h"
#include <iostream>
int checkingAccount::getChecks()
{
return numChecks;
}
void checkingAccount::setChecks(int c)
{
numChecks=c;
}
void checkingAccount::deposit(double d)
{
bankAccount::setBalance(bankAccount::getBalance()+d);
}
void checkingAccount::withdraw(double w)
{
bankAccount::setBalance(bankAccount::getBalance()-w);
}
void checkingAccount::getMonthlyStatement() const
{
bankAccount::getMonthlyStatement();
}
bankAccount.h:
#ifndef H_bankAccount
#define H_bankAccount
#include <string>
class bankAccount
{
public:
std::string getAcctOwnersName() const;
int getAcctNum() const;
double getBalance() const;
void getMonthlyStatement() const;
void setAcctOwnersName(std::string);
void setAcctNum(int);
void setBalance(double);
virtual void withdraw(double)=0;
virtual void deposit(double)=0;
private:
std::string acctOwnersName;
int acctNum;
double acctBalance;
};
#endif
bankAccount.cpp:
#include "bankAccount.h"
#include <iostream>
using std::string;
string bankAccount::getAcctOwnersName() const
{
return acctOwnersName;
}
int bankAccount::getAcctNum() const
{
return acctNum;
}
double bankAccount::getBalance() const
{
return acctBalance;
}
void bankAccount::setAcctOwnersName(string name)
{
acctOwnersName=name;
}
void bankAccount::setAcctNum(int num)
{
acctNum=num;
}
void bankAccount::setBalance(double b)
{
acctBalance=b;
}
void bankAccount::getMonthlyStatement() const
{
std::cout << "Name on Account: " << getAcctOwnersName() << std::endl;
std::cout << "Account Id: " << getAcctNum() << std::endl;
std::cout << "Balance: " << getBalance() << std::endl;
}
I know this is a lot of code to go through but can anyone help me understand why i cannot create an object from the class serviceChargeChecking the error is telling me that i cannot create an object from the abstract class but it doesn't seem to be abstract to me.
serviceChargeChecking implements void writeCheck(int), but the pure virtual function from checkingAccount has type void writeCheck(), so it's still pure in serviceChargeChecking, which makes the class abstract.
You have this in the abstract class checkingAccount:
virtual void writeCheck()=0;
but implement this in the derived class serviceChargeChecking:
void writeCheck(int);
The signature must be the same.
The writeCheck() method has different signatures in serviceChargeChecking and checkingAccount.
If you use C++11, use override in order to avoid this kind of error.
It's because your CheckingAcount has writeCheck() and serviceChargeChecking has writeCheck(int);
This probably due to the fact that you failed to Override checkingAccount's, writeCheck method, the abstract prototype was was
in checkingAccount class
virtual void writeCheck()=0;
and in serviceChargeChecking class
void writeCheck(int);
note the parameters, you didn't override checkingAccount's writeCheck you probably inherited it (implicitly), the serviceChargeChecking made a new writeCheck with an int parameter.

Undefined symbols for architecture x86_64 - Compiling inherited class

I currently have an abstract User class and a Student class which inherits from user. I'm attempting to initialize an instance of the Student class from main. I'm receiving this error
Undefined symbols for architecture i386:
"Student::Student()", referenced from:
_main in ccJo7npg.o
"Student::~Student()", referenced from:
_main in ccJo7npg.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
User Class:
#include <iostream>
#import <stdio.h>
#import <string.h>
using namespace std;
class User
{
public:
void setName(const string n)
{
name = n;
}
string getName()
{
return name;
}
void setUsername(const string u)
{
username = u;
}
string getUsername()
{
return username;
}
void setPassword(const string p)
{
password = p;
}
string getPassword()
{
return password;
}
void setID(const int ID)
{
this->ID=ID;
}
int getID()
{
return ID;
}
void setClassID(const int cid)
{
classID=cid;
}
int getClassID()
{
return classID;
}
void logOut()
{
cout<<"you have logged out"<<endl;
}
void print()
{
cout<< "Student : "<< ID << name << " "<< username << " " << password << endl;
}
virtual void menu()=0;
protected:
int classID, ID;
string name, username, password;
};
Student Class:
#include <iostream>
#include "User.h"
using namespace std;
class Student: public User
{
public:
Student()
{
classID=0;
ID=0;
username="";
name="";
password="";
}
~Student()
{
cout<<"destructor"<<endl;
}
void studyDeck(const int i)
{
}
void viewScores(const int)
{
}
void viewScores()
{
}
virtual void menu()
{
cout << "Student menu" << endl;
}
};
Main.cpp:
#include <iostream>
#include "User.h"
#include "Student.h"
using namespace std;
int main()
{
Student s;
return 0;
}
I'm compiling with g++ with " g++ User.cpp Student.cpp main.cpp "
Thanks!
GCC is not producing code for the Student constructor and destructor because they are defined inside of the class declaration. That's why those symbols are missing and generating a link error. At a minimum, you need to move the function bodies for the Student constructor and destructor outside of the class declaration and provide just the signature (no body) in the definition:
class Student: public User
{
Student();
~Student();
...
};
You would define these function bodies in Student.cpp after the class definition as follows:
Student::Student()
{
classID=0;
ID=0;
username="";
name="";
password="";
}
Student::~Student()
{
cout<<"destructor"<<endl;
}
Though it's not necessary, you should separate all of the function definitions from their implementation. To do this, you would omit the class definition from the Student.cpp file; and instead include Student.h in Student.cpp (even though you didn't post Student.h, it appears to be correct or the program would not have compiled). In other words, "Student.h" would contain "class Student { ... };" with just function signatures and no function bodies inside the braces and "Student.cpp" would contain all of the function definitions with bodies such as:
void Student::menu()
{
cout << "Student menu" << endl;
}
If you do this, you will also need #ifndef guards in the .h files as Kevin Grant explained.
You would treat User.cpp and User.h in the same way.