Why copy constructor changed previous object pointer member - c++

#include <iostream>
#include <string.h>
#include "Date.h"
#include "Employee.h"
using std::cout;
using std::endl;
using std::to_string;
class TestOps {
public:
int sex = 1;
string toString() {
return " sex:" + to_string(sex) ;
}
};
class Test {
public:
TestOps* testOps;
Test(const Test& t) :Test{} {
this->testOps = new TestOps{ *(t.testOps) };
};
Test() {
TestOps ops;
//this->testOps = new TestOps{}; // it will be ok with this way
this->testOps = &ops;
}
};
int main() {
// code not understand
Test t1;
cout <<"first testOps:" << t1.testOps->toString() << endl; // sex: 1
Test t2{ t1 };
cout << "first testOps:" << t1.testOps->toString() << endl; // sex: -858893460 ???? why?
cout << "second testOps:" << t2.testOps->toString() << endl; // sex: -858893460 ???? why?
return 0;
}
As you can see, why the first log is as expected while the later logs are not?
Also, t1.testOps address is different from t2.testOps which is as expected.
I have done some research but didn't find the answer. Maybe because I'm pretty new to cpp.

Related

Is there a way to use google test on OOP program?

I'm new to google test and currently I'm writing a test for my OOP program, my OOP program is like this:
#include <iostream>
#include <gtest/gtest.h>
using namespace std;
typedef unsigned int NUM;
class Employee
{
protected:
NUM MaSoThue;
private:
NUM Luong;
NUM CMND;
NUM a;
NUM b;
public:
Employee()
{
MaSoThue = 0;
Luong = 0;
CMND = 0;
}
Employee(NUM mst, NUM luong, NUM cmnd)
{
MaSoThue = mst;
Luong = luong;
CMND = cmnd;
}
//get
int getMaSoThue() const { return MaSoThue; }
int getLuong() const { return Luong; }
int getCMND() const {return CMND;}
//set
void setMaSoThue(NUM mst) {if (MaSoThue==0) MaSoThue = mst;}
void setLuong(NUM luong) {Luong = luong;}
void setCMND(NUM cmnd) {if (CMND==0) CMND = cmnd;}
};
int main()
{
// Objects
Employee PhucTri(111,222,333);
Employee MinhDang;
MinhDang.setMaSoThue(1234);
MinhDang.setLuong(2);
MinhDang.setCMND(8888);
//PhucTri
cout <<"MST cua Phuc Tri: "<< PhucTri.getMaSoThue()<<"\n";
cout << "Luong cua Phuc Tri: " << PhucTri.getLuong() << "\n";
cout << "CMND cua Phuc Tri: " << PhucTri.getCMND() << "\n\n";
//MinhDang
cout << "MST cua Minh Dang: " << MinhDang.getMaSoThue() << "\n";
cout << "Luong cua Minh Dang: " << MinhDang.getLuong() << "\n";
cout << "CMND cua Minh Dang: " << MinhDang.getCMND() << "\n";
}
I created a new file, which is below:
#include <gtest/gtest.h>
#include "FileCode.cc"
int main(){}
TEST(No1, PhucTri){
EXPECT_EQ(PhucTri.getMaSoThue(),111);
}
The compiler says that the object "PhucTri" isn't declared in this scope, but I did create it in my first file, is there any way I can get it right on the object ?
In general, Try to not include .cpp files, declare your class and its methods inside a .h file, define methods in .cpp and then create a test file that includes your header.
You have two options here, either define a test class that has an instance of your class follows instructions here.
Or do something like this :
#include <gtest/gtest.h>
#include "FileCode.h"
TEST(No1, PhucTri)
{
Employee PhucTri(111,222,333);
// initialize your data
// ......
EXPECT_EQ(PhucTri.getMaSoThue(),111);
}

class header: error: expected unqualified-id before 'char' while compiling

Sorry for bad english.
I am new on c++ and trying to understand to send references to class object.
But I get above error. If I use const char then error comes up for 'const' part.
Here is my code:
main:
#include <iostream>
#include "DelMe-ClassHeader.h"
using namespace std;
int main() {
char var1 [2];
int var2;
for (int i = 0; i < 2; i++) {
var1[i] = 2;
}
int var2 = 0;
tc = TestClass(var1, var2);
cout << "before tc.changeValue" << endl;
cout << "var1 is " << var1 << endl;
cout << "var2 is " << var2 << endl;
tc.changeValue()
cout << "before tc.changeValue" << endl;
cout << "var1 is " << var1 << endl;
cout << "var2 is " << var2 << endl;
}
header:
#ifndef TestClass
#define TestClass
#include <iostream>
using namespace std;
class TestClass {
public:
TestClass(char (& first)[2]}, int& second);
void changeValue ();
private:
char (& privArray)[2];
int& privInt;
};
#endif
cpp:
#include "DelMe-ClassHeader.h"
#include <iostream>
using namespace std;
TestClass::TestClass(char (& first)[15], int& second) {
this->priveArray = first;
this->privInt = second;
}
void TestClass::changeValue () {
privInt = atoi(privArray);
}
and the error is:
E:\Programing\CodeBlocks\Cpp\DelMe\DelMe\DelMe-ClassHeader.h|10|error: expected unqualified-id before 'char'
I gratefull for any help
The header contains two errors:
#define TestClass defines TestClass as an empty string. Therefore all occurences of TestClass will be replaced with an empty string, hence the errors. For more information read about the C++ preprocessor.
There is an extra } in the parameter list of TestClass.
Replace with this:
#ifndef TestClass_h_inc_
#define TestClass_h_inc_
#include <iostream>
using namespace std;
class TestClass {
public:
TestClass(char(&first)[2], int& second);
void changeValue();
private:
char(&privArray)[2];
int& privInt;
};
#endif

C++ How to implement this code into the heap properly

I am working on a class assignment to create three classes nested inside each other. I need to make constructors and deconstructors for each that have a message that goes along with them. Finally, I need to create an instance of each class using new and call the display() function to show their message, followed by delete.
I have completed the assignment but in the wrong way, and I am confused about how I can properly put the code into the heap instead of the stack (as I was advised by my course tutor).
This is what I started with: (this code seems to work well, but does not fulfill the assigned project)
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
class Hen {
public:
Hen();
~Hen();
string display(void) {
return ("Im a Hen");
}
class Nest;
friend Nest;
class Nest {
public:
Nest();
~Nest();
string display(void) {
return ("Im a Nest");
}
class Egg;
friend Egg;
class Egg {
public:
Egg();
~Egg();
string display(void) {
return ("Im an egg");
}
};
};
};
Hen::Hen() {
cout << "I construct Hens" << endl;
}
Hen::~Hen() {
cout << "I deconstruct Hens" << endl;
}
Hen::Nest::Nest() {
cout << "I construct Nests" << endl;
}
Hen::Nest::~Nest() {
cout << "I deconstruct Nests" << endl;
}
Hen::Nest::Egg::Egg() {
cout << "I construct Eggs" << endl;
}
Hen::Nest::Egg::~Egg() {
cout << "I deconstruct Eggs" << endl;
}
int main() {
Hen hone;
Hen::Nest none;
Hen::Nest::Egg eone;
string h, n, e;
h = hone.display();
n = none.display();
e = eone.display();
cout << h << "\n" << n << "\n" << e << endl;
}
Where I am stuck is when I try to implement my code inside the heap, it seems to break by the second class:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
class Hen {
public:
void display() {
cout << "Im a Hen" << endl;
}
class Nest;
friend Nest;
class Nest {
public:
void display() {
cout << "Im a Nest" << endl;
}
class Egg;
friend Egg;
class Egg {
public:
void display() {
cout << "Im an egg" << endl;
}
};
};
};
int main() {
Hen *hone = new Hen();
Hen::Nest *none = new Nest();
hone -> display();
none -> display();
}
Question 1:
If I remove all the information related to nest, the program runs Hen just fine and returns the "I'm a hen" statement. But, when I add in nest, the warning I recieve is
"error: expeected type-specifier before 'Nest'
Hen::Nest *none = new Nest();"
I do not understand what I am doing wrong as I did the exact same process for Hen and it worked. I do know that the error must be in the way Nest gets called through hen?
I apologize if this question is obvious, but I am just starting c++ and do not understand why I am getting these messages...
Thanks for your help!

C++ - Updating value in pointer gets overridden

I've recently begun learning C++ and I'm having some trouble updating a pointer in my Movie class. I've got a feeling I have an issue somewhere in my Move/Copy constructors but have been trying to solve this issue for hours, swapping pointers to references to values and finally coming here for help.
I have a class Movie, which contains a string name, string rating and int watched member variables. Another class Movies, holds a vector of the movies. On movie, my method increment_watched is supposed to increment the int watched by one, the value does get incremented but it seems like the value is not saved. The display_all_movies method in Movies, which simply displays the movies that it stores holds the old value for watched. I know the issue is probably something really small but I haven't been able to work out why the value isn't being saved.
If someone could explain why the pointer value seems to be getting overridden I'd appreciate it greatly. Thanks in advance!
Code is below, there is some debug couts in there.
Movie.h
#ifndef _MOVIE_H_
#define _MOVIE_H_
#include <string>
#include <iostream>
class Movie {
private:
std::string *name;
std::string *rating;
int *watched;
public:
std::string get_name();
std::string get_rating();
int get_watched();
void increment_watched();
Movie(std::string name, std::string rating, int watched_val); // normal constructor
Movie(const Movie &source); // copy constructor
Movie(Movie &&source); // move constructor
~Movie();
};
#endif // _MOVIE_H_
Movie.cpp
#include "Movie.h"
std::string Movie::get_name() {
return *name;
}
std::string Movie::get_rating() {
return *rating;
}
int Movie::get_watched() {
return *watched;
}
void Movie::increment_watched() {
std::cout << *watched << std::endl;
(*watched)++; // TODO FIX!
std::cout << *watched << std::endl;
}
Movie::Movie(std::string name, std::string rating, int watched_val)
: name{nullptr}, rating{nullptr}, watched{nullptr}{
std::cout << "Creating movie " << watched_val << " with normal constructor" << std::endl;
this->name = new std::string{name};
this->rating = new std::string{rating};
this->watched = new int{watched_val};
}
Movie::Movie(const Movie &source)
: Movie(*source.name, *source.rating, *source.watched) {
std::cout << "Creating movie " << *source.watched << " with copy constructor" << std::endl;
}
Movie::Movie(Movie &&source)
: Movie(*source.name, *source.rating, *source.watched) {
std::cout << "Creating movie " << *source.watched << " with move constructor" << std::endl;
source.name = nullptr;
source.rating = nullptr;
source.watched = nullptr;
}
Movie::~Movie() {
delete name;
delete rating;
delete watched;
}
Movies.h
#ifndef _MOVIES_H_
#define _MOVIES_H_
#include <vector>
#include <string>
#include <iostream>
#include "Movie.h"
class Movies {
private:
static int count;
std::vector<Movie> *movies;
public:
void add_movie(std::string &&name, std::string &&rating, int &&watch);
void increment_movie_count(std::string &&name);
void display_all_movies();
void count_movies();
Movies();
Movies(const Movie &source); // copy constructor
Movies(Movie &&source); // move constructor
~Movies();
};
#endif // _MOVIES_H_
Movies.cpp
#include "Movies.h"
int Movies::count = 0;
void Movies::add_movie(std::string &&name, std::string &&rating, int &&watch) {
bool contains {false};
for(auto movie : *movies) {
if(movie.get_name() == name) {
contains = true;
}
}
if(!contains) {
movies->push_back(Movie{name, rating, watch});
count++;
}
}
void Movies::increment_movie_count(std::string &&name) {
for(auto movie : *movies) {
if(movie.get_name() == name) {
movie.increment_watched();
}
}
}
void Movies::display_all_movies() {
for(auto movie : *movies) {
std::cout << "Title " << movie.get_name() << " Rating " << movie.get_rating() << " Watched " << movie.get_watched() << std::endl;
}
}
void Movies::count_movies() {
std::cout << "There are " << count << " movies " << std::endl;
}
Movies::Movies() {
movies = new std::vector<Movie>{};
}
Movies::~Movies() {
delete movies;
}
And finally main.cpp
#include <iostream>
#include "Movies.h"
using std::cout;
using std::endl;
int main() {
Movies *my_movies;
my_movies = new Movies();
(*my_movies).count_movies();
my_movies->add_movie("Big", "PG-13", 2);
my_movies->increment_movie_count("Big");
my_movies->display_all_movies();
return 0;
}
Changefor(auto movie : *movies) to for(auto& movie : *movies) to update the original movie objects. Otherwise, you're only updating copies of the movie objects.

elegant method to pass the data type for `boost::variant`

I need to find a better solution to pass the data type into boost::variant so that the function can retrieve the stored variate type elegantly. I have put up an implementation that works for me but I am concern there is a better way out there.
// file name: p192.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/variant.hpp>
using namespace std;
enum TypePassIn
{
INT_TYPE,
DOUBLE_TYPE,
STRING_TYPE,
PERSON_TYPE,
LAST_TYPE = PERSON_TYPE
};
struct Person
{
Person(int _age, string _name) : age(_age), name(_name) {}
int age;
string name;
};
void PrintVariant(map<string, boost::variant<int, double, string, Person> > _mapValues, TypePassIn tpi)
{
switch(tpi)
{
case INT_TYPE:
cout << boost::get<int>(_mapValues["int"]) << endl;
break;
case DOUBLE_TYPE:
cout << setprecision (15) << boost::get<double>(_mapValues["double"]) << endl;
break;
case STRING_TYPE:
cout << boost::get<string>(_mapValues["string"]) << endl;
break;
case PERSON_TYPE:
cout << "Age: " << (boost::get<Person>(_mapValues["Person"])).age;
cout << ", Name: " << (boost::get<Person>(_mapValues["Person"])).name << endl;
break;
default:
break;
}
}
int main(void)
{ map<string, boost::variant<int, double, string, Person> > mapValues;
mapValues["int"] = 10;
PrintVariant(mapValues, INT_TYPE);
mapValues["double"] = 100.99;
PrintVariant(mapValues, DOUBLE_TYPE);
mapValues["string"] = "Hello world";
PrintVariant(mapValues, STRING_TYPE);
mapValues["Person"] = Person(10, "Tom");
PrintVariant(mapValues, PERSON_TYPE);
}
~/Documents/C++/boost $ ./p192
10
100.99
Hello world
Age: 10, Name: Tom
As you can see from the code above, the implemented method can handle both native type and customized data type. In the ideal case, we can do it without introducing the enum TypePassIn
You can use the (static) visitor pattern, as shown in the tutorial of Boost.Variant.
struct VariantPrinter : boost::static_visitor<void>
{
void operator()(int int_val)
{
std::cout << int_val << std::endl;
}
void operator()(double double_val)
{
std::cout << std::setprecision(15) << double_val << std::endl;
}
// etc.
};
void PrintVariant(const boost::variant<...>& the_variant)
{
boost::apply_visitor(VariantPrinter(), the_variant);
}
int main()
{
std::map<std::string, boost::variant<...> > mapValues;
mapValues["int"] = 10;
PrintVariant(mapValues["int"]);
}