so basically I'm learning about game programming from this book, I'm currently on the part where it is explaining where is a data member is a pointer which points to object stored on the heap. it then does a couple of member functions such as destroy/copy or assign to another object.
so basically what I am trying to understand is when i am calling the three functions "testDestructor()"/ "testCopyConstructor(Critter aCopy) " and "testAssignmentOp()" is automatically going to the right member function, it might sound silly but unless I am misreading something, I don't see the book explaining how each fucntion is going to the correct member function.
I don't know its 11:30pm and maybe my brain is melted but I've reread this whole (few pages) detailed explanation of whats going on in the program three times and i cannot make heads or tails of how its correctly using the right member function without some kind of "connection"? perhaps I am missing something rudimentary.
P.S I understand what is happening with the code itself, I just don't know how the functions are calling the correct member functions
/Heap Data Member
//Demonstrates an object with a dynamically allocated data member
#include <iostream>
#include <string>
using namespace std;
class Critter
{
public:
Critter(const string& name = "", int age = 0);
~Critter(); //destructor prototype
Critter(const Critter& c); //copy constructor prototype
Critter& Critter::operator=(const Critter& c); //overloaded assignment op
void Greet() const;
private:
string* m_pName;
int m_Age;
};
Critter::Critter(const string& name, int age)
{
cout << "Constructor called\n";
m_pName = new string(name);
m_Age = age;
}
Critter::~Critter() //destructor definition
{
cout << "Destructor called\n";
delete m_pName;
}
Critter::Critter(const Critter& c) //copy constructor definition
{
cout << "Copy Constructor called\n";
m_pName = new string(*(c.m_pName));
m_Age = c.m_Age;
}
Critter& Critter::operator=(const Critter& c) //overloaded assignment op def
{
cout << "Overloaded Assignment Operator called\n";
if (this != &c)
{
delete m_pName;
m_pName = new string(*(c.m_pName));
m_Age = c.m_Age;
}
return *this;
}
void Critter::Greet() const
{
cout << "I'm " << *m_pName << " and I'm " << m_Age << " years old. ";
cout << "&m_pName: " << cout << &m_pName << endl;
}
void testDestructor();
void testCopyConstructor(Critter aCopy);
void testAssignmentOp();
int main()
{
testDestructor();
cout << endl;
Critter crit("Poochie", 5);
crit.Greet();
testCopyConstructor(crit);
crit.Greet();
cout << endl;
testAssignmentOp();
return 0;
}
void testDestructor()
{
Critter toDestroy("Rover", 3);
toDestroy.Greet();
}
void testCopyConstructor(Critter aCopy)
{
aCopy.Greet();
}
void testAssignmentOp()
{
Critter crit1("crit1", 7);
Critter crit2("crit2", 9);
crit1 = crit2;
crit1.Greet();
crit2.Greet();
cout << endl;
Critter crit3("crit", 11);
crit3 = crit3;
crit3.Greet();
}
I'm not exactly sure what you are asking, but:
The assignment operator is called when you use = in an expression, such as in your code:
crit1 = crit2;
crit3 = crit3;
Not to be confused with using the = symbol in a declaration (which you don't do anyway).
A constructor is called when you try to create an object, such as:
Critter crit2( "crit1", 7 ); // constructor
Other lines might look like:
Critter crit4; // default constructor
Critter crit5(crit3); // copy-constructor
If a constructor takes one argument that is another object of the same type, it's called a copy-constructor. This is just a terminology thing, there's no more fundamental distinction between copy-constructors and other constructors.
In your function void testCopyConstructor(Critter aCopy) , you can see that it has a parameter Critter aCopy. When you pass the argument crit to the function, it is like you create the parameter using the function argument:
Critter aCopy(crit); // equivalent
so calling this function will initialize aCopy using its copy-constructor.
A destructor is called whenever a local object goes out of scope, so when the } is reached at the end of testDestructor, then object toDestroy is destroyed.
what I am trying to understand is when i am calling the three functions "testDestructor()"/ "testCopyConstructor(Critter aCopy) " and "testAssignmentOp()" how is it automatically going to the right member function, it might sound silly but unless I am misreading something, I don't see the book explaining how each fucntion is going to the correct member function.
Instance (non-static) member functions are always passed a hidden pointer as their first argument - explicitly available within the class under the name this - which refers to the target object. This means that when a member function is invoked on/in any instance of a class (object), any in-scope references to member variables will be targeted to this instance via the pointer.
(This well documented and did not really need a new question. Hopefully your book mentions it elsewhere!)
Related
I know when a constructer is being called, then it gets created in the memory, and when it gets out of the block it gets destroyed unless it's static.
Know I have this code:
#include <iostream>
#include <string>
using namespace std;
class CreateSample
{
private:
int id;
public:
CreateSample(int i)
{
id = i;
cout << "Object " << id << " is created" << endl;
}
~CreateSample()
{
cout << "Object " << id << " is destroyed" << endl;
}
};
void fuct()
{
CreateSample o1(1);
static CreateSample o2(2);
}
CreateSample o3(3);
void fuct2(CreateSample o);
int main()
{
fuct();
static CreateSample o4(4);
CreateSample o5(5);
fuct2(o5);
return 0;
}
void fuct2(CreateSample o)
{
CreateSample o6 = o;
}
and my concern is in object o5, why it's getting called once and gets destroyed 3 times?
When you wrote fuct2(o5); you're calling the function fuct2 and passing the argument by value. This means a copy of the argument will be passed to the function using the implicitly defined copy constructor. Thus you get the 2nd destructor call corresponding this object o.
Moreover, in fuct2 you have CreateSample o6 = o; which will also use the implicitly defined copy constructor to create o6. Thus you will get a third call to the destructor corresponding to this o6.
You can confirm this for yourself by adding a copy ctor as shown below:
class CreateSample
{
//other code here
public:
CreateSample(const CreateSample&obj): id(obj.id)
{
std::cout<<"Copy ctor called"<<std::endl;
}
};
And the output you will get is:
Object 5 is created <------ctor called for o5
Copy ctor called <------copy ctor called for parameter o
Copy ctor called <------copy ctor called for object o6
Object 5 is destroyed <------destructor called for o6
Object 5 is destroyed <------destructor called for o
Object 5 is destroyed <------destructor called for o5
Demo
Though in this particular example you don't strictly require a custom copy constructor or a custom copy assignment operator, they may be needed in other situations. Refer to the rule of three.
CreateSample o5(5); calls the constructor CreateSample(int). fuct2(o5); and CreateSample o6 = o; call the implicitly-defined default copy constructor CreateSample(CreateSample const&). All three of these variables (o6, o, and o5) call the destructor ~CreateSample() when their scope is exited.
The fix is to follow the rule of three and also define a copy constructor and copy-assignment operator:
class CreateSample
{
// ...
CreateSample(CreateSample const& o) {
id = o.id;
cout << "Object " << id << " is copy-constructed" << endl;
}
CreateSample& operator=(CreateSample const& o) {
cout << "Object " << id << " is copy-assigned from " << o.id << endl;
id = o.id;
return *this;
}
}
Demo on Compiler Explorer
For a little background, I have been studying c++ for 3 months so I'm basically a newbie and I'm trying to understand classes that contain raw pointers as data members and how to use copy-contractors and move semantics with them.
So I have this simple class that contains a simple constructor/destructor and an unimplemented copy-constructor.
All I'm doing is creating an object using said class and then calling a member function with it.
So my question is:
Can I somehow always guaranty that when I call a member function I will make a copy of the object calling it and not pass it by reference?
You can easily pass something by reference if you add the "&" operator but what about passing something by value?
I have read that pass by value is the default way the compiler does it but for some reason when I execute my code the copy constructor is not called.
using namespace std;
class dog {
public:
string* name;
int* age;
dog(string NameVal = { "Null" }, int AgeVal = { 10 }) {
name = new string{ NameVal };
age = new int{ AgeVal };
cout << "constructor for " << *name << endl;
}
~dog() {
cout << "destructor for " << *name << " " << age << endl;
}
dog(const dog &source) {
cout << "copy constructor for " << *name << endl;
}
void talk(string text) {
cout << text << *name << endl;
}
};
int main() {
dog test;
test.talk("Test_Text ");
return 0;
}
So I expected the copy constructor to get called for the test object but it looks like it gets passed by reference using the "this" pointer.
How could I change that and actually make a copy of the object when calling the function?
Thanks for any help.
Well, if you want to copy the object and then call a function on the new object then you will need to do it explicitly:
dog test{};
dog{test}.talk("copy talk");
Note that you will also need to actually implement the copy constructor for this to work, otherwise class fields will be left uninitialized:
dog(const dog &source)
: name{new string{*(source.name)}}
, age{new int{*(source.age)}}
{
cout << "copy constructor for " << *name << endl;
}
Is there a way to always pass by value (Make a copy) rather than passing by reference when working with class member functions?
use a static operation receiving the instance by value
class dog {
...
static void talk(dog inst, string text) {
cout << text << *(inst.name) << endl;
}
...
};
int main() {
dog test;
dog::talk(test, "Test_Text ");
// or even
test.talk(test, "Test_Text ");
}
I am trying to write a copy constructor for the Shape class, so that it prints the address of the name of s2.
Here is my code:
class Shape {
private:
int x;
int y;
string * name;
public:
//constructor
Shape() {
cout << "Inside the constructor" << endl;
}
//Copy constructor
Shape(Shape& source) {
cout << "Copy constructor called" << endl;
name = new string[name];
copy(source.name, source.name, this->getName);
}
//Destructor
~Shape() {}
void setX(int px) {
x = px;
}
void setY(int py) {
y = py;
}
void setName(string * str) {
name = str;
}
string * getName() {
return name;
}
int main()
{
Shape s1;
s1.setName( new string("first shape") );
Shape s2(s1);
cout << s1.getName() << endl; //will display the address of name for s1
cout << s2.getName() << endl; //will display the address of name for s2
return 0;
}
As you created the string pointer member name for s1 and you're just copying it to s2 when invoking the copy constructor, it's just the expected behaviour that it displays the same address as for s1 - it simply copies the pointer.
If you want a unique name per shape, just create a static method / free function that creates a new name, and call that one in both, constructor and copy constructor, to give each new instance a unique name.
For what it's worth, using the new operator here is not really common (are you coming from a Java background?) - you may just want to use a regular std::string, in which case you don't have to do the memory management yourself (your code basically has a memory leak right now, because you don't call delete anywhere to free the memory allocated via new).
P.S.: Just saw you just edited and changed your code, while I was typing my answer... I won't keep track of the changes (please excuse that), but I leave my answer here for what it's worth.
Could you please try following code?
//Copy constructor
Shape(Shape& source) {
cout << "Copy constructor called" << endl;
name = new string[name];
*name = *source.name;
}
class A {
public:
A(void) { cout << "A::A" << endl; }
A(const A& a) { cout << "A::A(a)" << endl; }
virtual ~A(void) { cout << "A::~A" << endl; }
virtual void g(void) { cout << "A::g" << endl; }
};
class B : public A {
public:
B(void) { cout << "B::B" << endl; }
~B(void) { cout << "B::~B" << endl; }
void g(void){ cout << "B::g" << endl; }
};
void print(A c) {
cout << "print" << endl;
}
int main(void) {
A a;
B b;
A* c = &b;
c->g();
print(*c);
return 0;
}
I don't understand why this statement A::A(a) get's executed when calling c->g() or print(*c);
And I'm not quite sure to which part of the programm does the Method print belongs to?
Since you pass the argument by value to the print function, a copy must be made using the copy constructor. That is why your copy constructor is called when print is called.
If you change to call be reference (or by passing a pointer) then no copying will be made.
And as stated by others, print is a "normal" function, also known as a "free" function, or a non-member function. It "belongs" to the program, and exist in the global scope and have external linkage.
Print isn't a method, it's a function, as such it doesn't "belong" anywhere - it's simply part of your program.
Functions are from the age before Object-Orientation, though still have an important place.
The void print(A c) Function can be broken down as follows:
void, this is the return value, in this case - nothing.
print(, this is the name of the function.
A c), this means it will take a
single parameter of type A, named c.
As such A::A(const A &) is the copy constructor of the object A; Essentially this method will be called Every time an object of type A is copied into a new object of type A
When you call print(*c), you derefrence The pointer c, this results in a reference to the object pointed to by c (ie: an object of type A). This is then copy constructed into the print function, resulting in a temporary const A & that is used by the function.
This is why the Copy-constructor is called.
I am new to C++ programming, I got a doubt when I was reading a C++ regarding copy constructor. Why copy constructor will call when we pass object of class to a outside function as pass by value. Please go through my code as below.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class Line
{
public:
int getLength( void );
Line( int len ); // simple constructor
Line( const Line &obj); // copy constructor
~Line(); // destructor
private:
int *ptr;
};
// Member functions definitions including constructor
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj)
{
cout << "Copy constructor allocating ptr." << endl;
ptr = new int;
*ptr = *obj.ptr; // copy the value
}
Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength( void )
{
return *ptr;
}
void display(Line obj)//here function receiving object as pass by value
{
cout << "Length of line : " << obj.getLength() <<endl;
}
// Main function for the program
int main( )
{
Line line(10);
display(line);//here i am calling outside function
_getch();
return 0;
}
In the above the I am passing object of class as parameter and display function receiving it as pass by value. My doubt is when I pass object to a function which is not a member of class why copy constructor is calling. if I receive object as reference in display() function[i.e display(Line &Obj)] it is not calling the copy constructor. Please help me what is the difference.
When you pass something by value, the copy constructor is used to initialize the parameter that's passed -- i.e., what's passed is a copy of whatever you give, so of course the copy constructor is used to create that copy.
If you don't want the value copied, pass by (probably const) reference instead.