How to get class name at compile time? [duplicate] - c++

This question already has answers here:
How can I get the class name from a C++ object?
(9 answers)
Closed 8 months ago.
#include <iostream>
#include <math.h>
#include <string>
using namespace std;
class People{
public:
string name;
int age;
bool educated;
People(){
cout << [name] << "class people is initialised" << endl;
}
~People(){
cout << [name] << "class people is destroyed" << endl;
}
private:
double worth;
};
int main(){
People Joe;
}
how do i display that class name in the constructor and destructor?
I saw another method was calling the function specifically in main() however that is not what i want. I want to try to display the class name upon its creation and destruction

Welcome to stackoverflow and C++!
I tool the liberty of fixing some smaller issues with the code:
<cmath> is the proper C++ header, use that instead of <math.h> (the C header. C and C++ are different).
Do not build an early habit of using namespace std. Yes, it seems convenient, but read here why you should not do it.
Using std::endl will likely drop your performance. Read here about the differences. using \n works just as good, is cross-platform-compatible and even less to type.
Does this achieve what you want?
#include <cmath>
#include <iostream>
#include <string>
class People{
public:
std::string name;
int age;
bool educated;
People(){
std::cout << typeid(*this).name() << "class people is initialised\n";
}
~People(){
std::cout << typeid(*this).name() << "class people is destroyed\n";
}
private:
double worth;
};
int main(){
People Joe;
}
Responding to the comment:
People(std::string const& str)
: name(str)
{
std::cout << name << " class people is initialised\n";
}
////
int main(){
Person Joe("Joe");
}
Note this important difference:
People(std::string str) will create a copy of the string (which is usually expensive).
People(std::string const& str) will create a constant reference. Constant means it can not be changed and since it is a reference, it will not be copied here (it will be copied into the class member though).

You can use the preprocessor to get the name like this: typeid(*this).name().
P.S. Don't use using namespace std. It can make your code unclear.

Related

C++ use iostream inside class [duplicate]

This question already has an answer here:
Does not name a type
(1 answer)
Closed 2 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I'm using iostream and map. When I try to set the functions, they throw an error.
My code:
#include "string"
#include "iostream"
#include "map"
using namespace std;
class myClass {
map<string, string> Map;
Map["Ziv"] = "Sion";
cout << Map["Ziv"];
};
My error:
error: 'Map' does not name a type
error: 'cout' does not name a type
Why I can't use iostream and cout?
Why I can't use iostream and cout?
Because a class cannot (directly) contain expression statements. It can contain only member declarations.
Expression statements can only be within functions. This would be correct for example:
class main {
map<string, string> Map;
void example_function() {
Map["Ziv"] = "Sion";
cout << Map["Ziv"];
}
};
you can't have a C++ progran without the main function so please create int main(){}. And change the double quotes in the #include directives to angle brackets like below:
#include <string>
#include <iostream>
#include <map>
using namespace std;
class myClass {
public:
int myFunc();
};
myClass :: int myFunc(){
map<string, string> Map;
Map["Ziv"] = "Sion";
cout << Map["Ziv"];
}
int main(){
myClass myclass;
myclass.myFunc();
return 0;
}
Please consider i am a beginner and forgive my mistakes if any.
In object oriented languages, like C++, you can't write expressions/statements in a class. You may want to use a function. Example:
#include<iostream>
using std::cout;
class Example {
public:
void sayHello() {
cout << "Hello!";
}
}
int main() {
new Example().sayHello(); // Prints Hello!
}
You have to enter the cout in a function, inside the class you can't execute functions, you just can describe them or variables / objects.
Class is an Entity which contains related data members and the operations to modify or access those data members. No expression can be executed within the class. It does not make an sense to do something that you can not access. Because the only way to access and modify something are operations.
Yes in case if you want to print something when the class object is created, you can do that in Constructor. May be this is what you want to do:
#include <map>
#include <iostream>
#include <string>
class myClass {
private:
std::map<std::string, std::string> Map;
public:
myClass(const std::string& key, const std::string& value){
Map[key] = value;
std::cout << value;
}
};
int main(){
myClass cls("Ziv", "Sion");
}

Adding inheritance in C++ multiple class file

I am learning C++ from the book called "Beginning C++ through Game Programming" and this problem showed up. The following code was originally 1 file, but I had to divide it into multiple classes.
Now, I am stuck at inheritance problem. I watched videos, read tutorials about it but nothing seemed to help. The book doesn't help either. I need to add the following attributes:
Use the multiple file class version (I am using it)
From a critter base class -- add at least 2 inheritance critters
The base class should have at least 2 attributes (data)
The inherited class should have at least 2 additional traits different from the base class and the other inherited class
Add the appropriate functions for all the attributes -- both base and inherited
Add appropriate menu items
Any help here would be highly appreciated!
critter.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Critter
{
public:
Critter(const string& name = "");
string GetName() const;
private:
string m_Name;
};
critterImp.cpp
#include <critter.h>
Critter::Critter(const string& name):
m_Name(name)
{}
inline string Critter::GetName() const
{
return m_Name;
}
farm.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Critter;
class Farm
{
public:
Farm(int spaces = 1);
void Add(const Critter& aCritter);
void RollCall() const;
private:
vector<Critter> m_Critters;
};
farmImp.cpp
#include <farm.h>
#include <critter.h>
Farm::Farm(int spaces)
{
m_Critters.reserve(spaces);
}
void Farm::Add(const Critter& aCritter)
{
m_Critters.push_back(aCritter);
}
void Farm::RollCall() const
{
for (vector<Critter>::const_iterator iter = m_Critters.begin();
iter != m_Critters.end();
++iter)
{
cout << iter->GetName() << " here.\n";
}
}
critFarmTest.cpp
#include <farm.h>
#include <critter.h>
int main()
{
Critter crit("Poochie");
cout << "My critter's name is " << crit.GetName() << endl;
cout << "\nCreating critter farm.\n";
Farm myFarm(3);
cout << "\nAdding three critters to the farm.\n";
myFarm.Add(Critter("Moe"));
myFarm.Add(Critter("Larry"));
myFarm.Add(Critter("Curly"));
cout << "\nCalling Roll...\n";
myFarm.RollCall();
return 0;
}

Weird behavior with OOP and string pointers

Here's my code:
#include <iostream>
#include <string>
class Human
{
public:
std::string * name = new std::string();
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << Human::name << std::endl;
}
int main()
{
Human * martha;
martha->name = new std::string("Martha");
martha->introduce();
return 0;
}
Well, it's supposed to print a message out like:
"Hello, my name is Martha" but it doesn't print neither the "Hello, my name is" string or the "Martha" name. Why does it occur?
The fix is simple and is to completely remove all pointers; see the code below. There are a number of issues with your code that I could address in detail, including memory leaks, uninitialized variables, and general misuse of pointers, but it seems that you're possibly coming from a different language background and should spend time learning good practice and the important semantics and idioms in modern C++ from a good C++ book.
#include <iostream>
#include <string>
class Human
{
public:
std::string name;
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human martha;
martha.name = "Martha";
martha.introduce();
return 0;
}
Few modifications are required to the code.
Updated code along with the comments to the change made are included below.
#include <iostream>
#include <string>
class Human
{
public:
//Removed pointer to a string
//Cannot have an instantiation inside class declaration
//std::string * name = new std::string();
//Instead have a string member variable
std::string name;
void introduce();
};
void Human::introduce()
{
//Human::name not required this is a member function
//of the same class
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human *martha = new Human();
//Assign a constant string to string member variable
martha->name = "Martha";
martha->introduce();
return 0;
}
As suggested by #alter igel - The Definitive C++ Book Guide and List would be a good place to start.
#include <iostream>
#include <string>
class Human {
public:
void Human(std::string* n) { name = n; }
void introduce();
private:
std::string* name;
};
void Human::introduce() {
std::cout << "Hello, my name is " << name << std::endl;
}
int main() {
Human* martha = new Human(new std:string("Martha"));
martha->introduce();
return 0;
}
Try that. The difference is that you don't initialise the variable in the class definition, and you initialise the name with the constructor. You can split the method definition out into it's own section, but it's only one line and is fine being inside the class definition.

Struggling with C++ "was not declared in this scope"

Can anyone tell me why i get the error "name was not declared in the scope when running this?
Thanks.
class lrn11_class{
public:
void setName(string x){
name = x;
}
string getName(){
return name;
}
private:
string lrn11_name;
};
int main()
{
lrn11_class lrn11_nameobject;
lrn11_nameobject.setname("Zee");
cout << lrn11_nameobject.getname() << endl;
return 0;
}
This should work - see comments (BTW use std:: - Why is "using namespace std" considered bad practice?)
#include <iostream>
#include <string>
class lrn11_class{
public:
void setName(const std::string& x){ // Potentially saves copying overhead
name = x;
}
std::string getName() const { // Look up const and its uses
return name;
}
private:
std::string name; // - Used: string lrn11_name; but functions use name!
};
int main()
{
lrn11_class lrn11_nameobject;
lrn11_nameobject.setName("Zee"); // Fixed typo
std::cout << lrn11_nameobject.getName() << std::endl; // Ditto
return 0;
}
You have declare lrn11_name as a member varible for this class. But in set and get functions you are using name.
Other than than you need to call functions as you have defined.
so instead of :-
lrn11_nameobject.setname("Zee");
cout << lrn11_nameobject.getname() << endl;
You have to use following code :-
lrn11_nameobject.setName("Zee");
cout << lrn11_nameobject.getName() << endl;
Make sure that
#include <iostream>
using namespace std;
should be included.

Displaying object name inside destructor

Inside FileTwo.h
#include"iostream"
using namespace std ;
class FileTwo{
public:
FileTwo(){
cout<<"constructor for";//Here want to show the object for which the constructor has been called
}
~Filetwo(){
cout<<"Destructor for ";//Here want to show the object for which the destructor has been called
};
Inside main.cpp
#include"Filetwo.h"
int main(){
FileTwo two ;
return 0;
}
I know this sample program is very small , so we can able to find out the object for which the constructor and destructor has been called . But for big project is there any way to know the object name ? Thanks in advance .
It is possible. If your compile supports __PRETTY_FUNCTION__ or __func__ (see this), then you can do this:
#include <iostream>
using namespace std;
class FileTwo{
public:
FileTwo(){
cerr<<"constructor for "<< __PRETTY_FUNCTION__ <<" at "<<&(*this)<<endl;
}
~FileTwo(){
cerr<<"Destructor for "<< __PRETTY_FUNCTION__ <<" at "<<&(*this)<<endl;
}
};
int main(){
FileTwo two;
return 0;
}
Note that I've also printed to cerr to ensure that this output gets flushed immediately and isn't lost if the program crashes. Also, since each object has a unique *this pointer, we can use that to see when particular objects are being made or getting killed.
The output for the above program on my computer is:
constructor for FileTwo::FileTwo() at 0x7fff641cde40
Destructor for FileTwo::FileTwo() at 0x7fff641cde40
Note that __func__ is a C99 standard identifier. C++0x adds support in the form of an "implementation-defined string".
__FUNCTION__ is a pre-standard extension supported by some compilers, including Visual C++ (see documentation) and gcc (see documentation).
__PRETTY_FUNCION__ is a gcc extension, which does the same sort of stuff, but prettier.
This question has more information on these identifiers.
Depending on your compiler, this may return the name of the class, though it may be a little mangled.
#include <iostream>
#include <typeinfo>
using namespace std;
class FileTwo{
public:
FileTwo(){
cerr<<"constructor for "<< typeid(*this).name() <<" at "<<&(*this)<<endl;
}
~FileTwo(){
cerr<<"Destructor for "<< typeid(*this).name() <<" at "<<&(*this)<<endl;
}
};
int main(){
FileTwo two;
return 0;
}
If you are trying to get the name of the variable to which the class is instantiated (two in your case), then there is not, to my knowledge, a way to do this. The following will emulate it:
#include <iostream>
#include <string>
using namespace std;
class FileTwo{
public:
FileTwo(const std::string &myName) : myName(myName) {
cerr<<"constructor for "<< myName <<" at "<<&(*this)<<endl;
}
~FileTwo(){
cerr<<"Destructor for "<< myName <<" at "<<&(*this)<<endl;
}
private:
std::string myName;
};
int main(){
FileTwo two("two");
return 0;
}
Unless you name the object, it is not possible. Something like this :
#include <iostream>
#include <string>
using namespace std;
class FileTwo {
public:
FileTwo(const std::string &myName) : name(myName){
cout<<"constructor for" << name;//Here want to show the object for which the constructor has been called
}
~Filetwo(){
cout<<"Destructor for " << name;//Here want to show the object for which the destructor has been called
}
private:
std::string name;
};
and then change the main into :
#include"Filetwo.h"
int main(){
FileTwo two("two 11");
}
It is not possible to name the object,all what you can do is making a private variable to hold the name.
using namespace std;
class myClass
{
private:
string className;
public:
~myClass()
{
cout<<this->className;
}
};
you can create setters and getters for you variable.
void SetName(string name)
{
this->className = name;
}
string GetName()
{
return this->className;
}