Counting number of objects of different classes - c++

I would like to count the number of objects that my program creates over its lifetime. Based on the solution provided here:
how to count the number of objects created in c++
I have the following code:
#include <iostream>
using namespace::std;
using std::cout;
using std::endl;
template <typename T>
struct counter
{
counter()
{
objects_created++;
objects_alive++;
}
virtual ~counter()
{
--objects_alive;
}
static int objects_created;
static int objects_alive;
};
template <typename T> int counter<T>::objects_created(0);
template <typename T> int counter<T>::objects_alive(0);
class X : counter<X>
{
int a;
};
class Y : counter<Y>
{
int b;
};
void fooX(class X x) {
cout << "passing object" << endl;
}
void fooY(class Y& y) {
cout << "passing reference" << endl;
}
int main()
{
cout << "created: " << " X:" << counter<X>::objects_created << " Y:" << counter<Y>::objects_created << endl;
cout << "alive: " << " X:" << counter<X>::objects_alive << " Y:" << counter<Y>::objects_alive << endl;
X x;
Y y;
cout << "created: " << " X:" << counter<X>::objects_created << " Y:" << counter<Y>::objects_created << endl;
cout << "alive: " << " X:" << counter<X>::objects_alive << " Y:" << counter<Y>::objects_alive << endl;
fooX(x);
fooY(y);
cout << "created: " << " X:" << counter<X>::objects_created << " Y:" << counter<Y>::objects_created << endl;
cout << "alive: " << " X:" << counter<X>::objects_alive << " Y:" << counter<Y>::objects_alive << endl;
int ui;
cin >> ui;
}
I expected that since x is passed by value, a copy of it is made inside fooX making the total number of objects of class X to be 2 while since y is passed by reference, the total number of objects of class Y to be 1.
Yet, the output of the code is as follows:
created: X:0 Y:0
alive: X:0 Y:0
created: X:1 Y:1
alive: X:1 Y:1
passing object
passing reference
created: X:1 Y:1
alive: X:0 Y:1
Why does not the number of Xs created be 2?

A copy constructor is automatically added to your counter class, and that automatically created copy constructor doesn't increment your static variables.
Write a copy constructor which does that:
counter(counter const&)
{
objects_created++;
objects_alive++;
}
Note that your destructor should probably not be virtual, unless you intend to delete dynamically created instances of derived classes via pointers or references to counter. As it stands, it's just premature pessimisation because it needlessly increases the size of your objects.

Related

Questions about right value reference in C++

#include <iostream>
using namespace std;
void swap(int& a, int& b)
{
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
int tmp{move(a)};
cout << "address of tmp: " << &tmp << " value of tmp: " << tmp << endl;
a = move(b);
b = move(tmp);
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
}
void swap_no_move(int& a, int& b)
{
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
int tmp{ a };
cout << "address of tmp: " << &tmp << " value of tmp: " << tmp << endl;
a = b;
b = tmp;
cout << "address of a: " << &a << " value of a: " << a << endl;
cout << "address of b: " << &b << " value of b: " << b << endl;
}
int main() {
int a = 10;
int b = 5;
swap(a, b);
cout << endl;
int c = 10;
int d = 5;
swap_no_move(c, d);
cin.get();
return 0;
}
I have two swap functions: swap and swap_no_move. According to what I read from the book, there should be no "copy" in function swap which means the address of tmp should be the same for tmp and an in function swap. However, the output I got shows there is no difference between these two functions, did I do something wrong?
The definition
int tmp{move(a)};
doesn't move the reference or the variable a itself. It creates a brand new variable tmp which the compiler allocates space for. Then the value of a is moved into tmp.
And since moving int values can't really be done, it's exactly the same as
int tmp = a;

Understanding working of copy constructor

To understand working of constructor, copy constructor, destructor, I wrote the following code.
#include <iostream>
using namespace std;
class Cat
{
public:
Cat();
Cat(Cat&);
~Cat();
int itsage;
};
Cat::Cat()
{
cout << "Constructor called\n";
cout << this << endl;
itsage=2;
}
Cat::Cat(Cat& theCat)
{
cout << "Copy constructor called\n";
cout << this << endl;
itsage=theCat.itsage;
}
Cat::~Cat()
{
cout << "Destructor called\n";
cout << this << endl;
}
Cat myFunction(Cat Frisky)
{
cout << "Inside myFunction\n";
cout << "Frisky's address : " << &Frisky ;
cout << "\nFrisky's age: " << Frisky.itsage << "\n";
Frisky.itsage=100;
cout << "Reassigned Frisky's age: "<< Frisky.itsage << "\n";
return Frisky;
}
int main()
{
Cat Mani;
cout << "Mani's address : " << &Mani ;
cout << "\nMani's age: " << Mani.itsage << "\n";
myFunction(Mani);
return 0;
}
I got output as follows:
Constructor called
0x61ff04
Mani's address : 0x61ff04
Mani's age: 2
Copy constructor called
0x61ff0c
Inside myFunction
Frisky's address : 0x61ff0c
Frisky's age: 2
Reassigned Frisky's age: 100
Copy constructor called
0x61ff08
Destructor called
0x61ff08
Destructor called
0x61ff0c
Destructor called
0x61ff04
Everything is ok to me except what is stored at address 0x61ff08 when there was second call to copy constructor? Means we can see what is stored at addresses 0x61ff0c and 0x61ff04 which are nothing but Frisky and Mani. Then what is that invisible thing at 0x61ff08?
I thought of making that object visible by making a small change in main function.
#include <iostream>
using namespace std;
class Cat
{
public:
Cat();
Cat(Cat&);
~Cat();
int itsage;
};
Cat::Cat()
{
cout << "Constructor called\n";
cout << this << endl;
itsage=2;
}
Cat::Cat(Cat& theCat)
{
cout << "Copy constructor called\n";
cout << this << endl;
itsage=theCat.itsage;
}
Cat::~Cat()
{
cout << "Destructor called\n";
cout << this << endl;
}
Cat myFunction(Cat Frisky)
{
cout << "Inside myFunction\n";
cout << "Frisky's address : " << &Frisky ;
cout << "\nFrisky's age: " << Frisky.itsage << "\n";
Frisky.itsage=100;
cout << "Reassigned Frisky's age: "<< Frisky.itsage << "\n";
return Frisky;
}
int main()
{
Cat Mani;
cout << "Mani's address : " << &Mani ;
cout << "\nMani's age: " << Mani.itsage << "\n";
Cat Sweety = myFunction(Mani);
cout << "Sweety's age : " << Sweety.itsage ;
return 0;
}
But received an error as follows :
ppp.cpp: In function 'int main()':
ppp.cpp:47:25: error: invalid initialization of non-const reference of type 'Cat&' from an rvalue of type 'Cat'
Cat Sweety = myFunction(Mani);
~~~~~~~~~~^~~~~~
ppp.cpp:19:2: note: initializing argument 1 of 'Cat::Cat(Cat&)'
Cat::Cat(Cat& theCat)
^~~
I really didn't get what went wrong.
Your first code returns a copy of Frisky from myFunction, that is where the additional copy comes from.
Your second code doesn't work because your copy constructor erroneously takes a non-const reference and you can't pass the temporary value returned from myFunction to a non-const reference.
Not directly related to your question but you should obey the rule of three and implement the assignment operator too.
Cat(Cat &);
Use const here.
Cat(const Cat &);
Not related but consider using initialisation like this.
Cat Sweety{myFunction(Mani)};

C++ proper usage of ostream inside a class and passing arguments?

I've recently started learning c++ and for the life of me, I can't seem to get the syntax of using ostream in a class and what arguments should I pass. Here's the code:
This is the class in question:
#include <iostream>
#include <string>
using namespace std;
class Pokemon{
friend ostream& operator<<(ostream&, Pokemon);
public:
string name, level, cp;
Pokemon(string x="Pikachu", string y="5", string z="1000"){
name = x;
level = y;
cp = z;
}
Pokemon name(){
return this->name;
}
Pokemon level(){
return this->level;
}
Pokemon cp(){
return this->cp;
}
Pokemon display_stats(){
cout << this-> name << "stats are:" << endl;
cout << " " << "Attack: 2716.05" << endl;
cout << " " << "Defence: 1629.63" << endl;
cout << " " << "HP: 1086.42" << endl;
}
};
template<typename TYPE> //i dont understand this and the things i've written down here are only based on samples i've seen
ostream& operator<<(ostream& os, Pokemon & c){
os << "The level of " << c.name << " is" << c.level << " with cp of " << c.cp;
}
As you could see, I already tried constructing the ostream thing but I don't really understand how it works. This is my main function:
int main()
{
Pokemon a, b, c, d;
a = Pokemon();
b = Pokemon("Weezing");
c = Pokemon("Nidoking", 100);
d = Pokemon("Mewtwo", 50, 5432.1);
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
cout << "Jessie: You are no match to me! Go " << b.name << "!" << endl;
cout << "Gary: Go lvl " << c.level << " " << c.name << "! Crush them" << endl;
cout << "Ash: " << a.name << " can do it even thouh he is only level " << a.level << endl;
cout << "Jessie: Hahaha! My " << b.name << " CP is " << b.cp << endl;
cout << "Gary: "<< c.name << " CP is " << c.cp << endl;
cout << "Ash: " << a.name << " CP is " << a.cp << endl;
cout << "Giovanni: Behold " << d.name << " is here." << endl;
d.display_stats();
return 0;
}
I'm getting errors of:
no instance of constructor "Pokemon::Pokemon" matches the argument list -- argument types are: (const char [9], int) //on line c = Pokemon("Nidoking", 100);
no instance of constructor "Pokemon::Pokemon" matches the argument list -- argument types are: (const char [7], int, double) //on line d = Pokemon("Mewtwo", 50, 5432.1);
All of your Pokemon class methods are returning the wrong type. And your main() is not calling any of the methods correctly at all.
Change your Pokemon class to look more like this:
#include <iostream>
#include <string>
using namespace std;
class Pokemon {
private:
string m_name;
int m_level;
double m_cp;
friend ostream& operator<<(ostream&, const Pokemon&);
public:
Pokemon(string x="Pikachu", int y=5, double z=1000) {
m_name = x;
m_level = y;
m_cp = z;
}
string name() const {
return m_name;
}
int level() const {
return m_level;
}
double cp() const {
return m_cp;
}
void display_stats() const {
cout << m_name << " stats are:" << endl;
cout << " " << "Attack: 2716.05" << endl;
cout << " " << "Defense: 1629.63" << endl;
cout << " " << "HP: 1086.42" << endl;
}
};
ostream& operator<<(ostream& os, const Pokemon &c) {
os << "The level of " << c.m_name << " is " << c.m_level << " with cp of " << c.m_cp;
return os;
}
And then change main() to look more like this:
int main()
{
Pokemon a;
Pokemon b("Weezing");
Pokemon c("Nidoking", 100);
Pokemon d("Mewtwo", 50, 5432.1);
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
cout << "Jessie: You are no match to me! Go " << b.name() << "!" << endl;
cout << "Gary: Go lvl " << c.level() << " " << c.name() << "! Crush them" << endl;
cout << "Ash: " << a.name() << " can do it even though he is only level " << a.level() << endl;
cout << "Jessie: Hahaha! My " << b.name() << " CP is " << b.cp() << endl;
cout << "Gary: " << c.name() << " CP is " << c.cp() << endl;
cout << "Ash: " << a.name() << " CP is " << a.cp() << endl;
cout << "Giovanni: Behold " << d.name() << " is here." << endl;
d.display_stats();
return 0;
}
Live Demo

Initialize member variables with multiple constructor calls

I'm trying to execute the following code:
#include <iostream>
using namespace std;
class ABC {
private:
int x, y;
public:
ABC(){
cout << "Default constructor called!" << endl;
ABC(2, 3);
cout << x << " " << y << endl;
}
ABC(int i, int j){
cout << "Parameterized constructor called with parameters "<< i << " " << j << "!" << endl;
x = i;
y = j;
cout << x << " " << y << endl;
}
};
int main(){
ABC a;
return 0;
}
I am getting the following output:
Default constructor called!
Parameterized constructor called with parameters 2 3!
2 3
-858993460 -858993460
Shouldn't the member variables be initialized with values 2 and 3?
ABC(2, 3); doesn't call the constructor to initialize the members, it just create a temporary variable which will be destroyed immediately.
If you meant delegating constructor you should:
ABC() : ABC(2, 3) {
cout << "Default constructor called!" << endl;
cout << x << " " << y << endl;
}
Note this is a C++11 feature. You can add a member function if you can't use C++11.
class ABC {
private:
int x, y;
init(int i, int j) {
x = i;
y = j;
}
public:
ABC(){
cout << "Default constructor called!" << endl;
init(2, 3);
cout << x << " " << y << endl;
}
ABC(int i, int j){
cout << "Parameterized constructor called with parameters "<< i << " " << j << "!" << endl;
init(i, j);
cout << x << " " << y << endl;
}
};
You create a temporary variable in ABC() body. You can use this syntax to overcome this:
class ABC
{
private:
int x, y;
public:
ABC() : ABC(2,3)
{
std::cout << "Default constructor called!" << std::endl;
}
ABC(int i, int j)
{
std::cout << "Parameterized constructor called with parameters "<< i << " " << j << "!" << std::endl;
x = i;
y = j;
std::cout << x << " " << y << std::endl;
}
};

C++ no operator "<<" match these operand (inheritance)

I have just recently started class inheritance in c++. While I was making a "Test" program, a error occurred with the cout statement. No clue how to fix it and would be appreciate your response.
#include <iostream>
using namespace std;
class Power{
public:
void isWeak(){
cout << " Weak"<< endl;
}
void isStrong(){
cout << " Strong" << endl;
}
};
class Person:public Power{};
class Person2:public Power{};
int main(){
Person human;
Person2 human2;
cout << "Human is " << human.isWeak() << endl; //error
cout << "Human 2 is " << human2.isStrong() << endl; //error
system("pause");
return 0;
}
the main()'s cout statement has that error between the output and human
Change the functions to
char const *isWeak(){
return " Weak";
}
char const *isStrong(){
return " Strong";
}
As currently defined, both functions have void return type, which means the cout statements within main are trying to print void, which doesn't make sense, and is the cause of the error.
You are attempting to print a void:
cout << "Human is " << human.isWeak() << endl;
is the same as typing
cout << "Human is " << void << endl;
Which will not compile. What you need to do is define your functions in either of the following ways:
class Power
{
public:
std::string isWeak()
{
return std::string(" is weak");
}
std::string isStrong()
{
return std::string(" is strong");
}
};
Or, change your code:
cout << "Human is ";
human.isWeak();
cout << endl;
cout << "Human 2 is ";
human2.isStrong();
cout << endl;
Problem is with isWeak() and isStrong() return type. these two functions return void and you are trying to print it. you can try this-
cout << "Human is " ;
human.isWeak();
cout << endl;
cout << "Human 2 is " ;
human2.isStrong();
cout << endl;
You're trying to 'print' a 'void' statement in cout << "Human is " << human.isWeak() << endl;
You'll need to change your isWeak and isStrong functions to return a std::string/const char* or change the way you call them:
to string:
const char* isWeak() {
return " Weak";
}
// then you can do
cout << "Human is " << human.isWeak() << endl;
Or change the way you call the function:
cout << "Human is ";
human.isWeak();
Your isWeak and isStrong functions are void they do not return anything; calling cout << human.isWeak() is expecting isWeak to return something (an int, string, double, etc.).